columnFvMesh.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2018-2021 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "columnFvMesh.H"
30 #include "IOobjectList.H"
31 #include "fieldDictionary.H"
32 #include "vectorIOField.H"
33 #include "emptyPolyPatch.H"
34 #include "topoSet.H"
36 
37 // * * * * * * * * * * * * * * * Static Members * * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
41 namespace simplifiedMeshes
42 {
43  defineTypeNameAndDebug(columnFvMeshInfo, 0);
44  defineTypeNameAndDebug(columnFvMesh, 0);
45 
47  (
48  simplifiedFvMesh,
49  columnFvMesh,
50  time
51  );
52 }
53 }
54 
55 
56 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
57 
58 bool Foam::simplifiedMeshes::columnFvMeshInfo::setPatchEntries
59 (
60  const Time& runTime
61 )
62 {
63  IOobject boundaryIO
64  (
65  "boundary",
68  runTime,
71  false
72  );
73 
74  const wordHashSet constraintPatches(polyPatch::constraintTypes());
75 
76  if (boundaryIO.typeHeaderOk<polyBoundaryMesh>(true))
77  {
78  polyBoundaryMeshEntries allPatchEntries(boundaryIO);
79 
80  Info<< "Creating simplified mesh using " << allPatchEntries.path()
81  << endl;
82 
83  for (const entry& e : allPatchEntries)
84  {
85  const word type(e.dict().get<word>("type"));
86 
87  if (!constraintPatches.found(type))
88  {
89  if (e.dict().get<label>("nFaces"))
90  {
92  }
93  patchEntries_.add(e.keyword(), e.dict());
94  }
95  }
96 
97  return true;
98  }
99  else
100  {
101  // No boundary file - try reading from a field
102  IOobjectList objects
103  (
104  runTime,
105  runTime.timeName(),
107  );
108 
109  if (objects.empty())
110  {
111  // No fields - cannot create a mesh
112  return false;
113  }
114 
115  const IOobject& io = *objects.begin()();
116 
117  if (io.instance() == runTime.constant())
118  {
120  << "No time directories found for field reading"
121  << exit(FatalError);
122  }
123 
124  const fieldDictionary fieldDict(io, io.headerClassName());
125 
126  Info<< "Creating simplified mesh from field "
127  << fieldDict.objectPath()
128  << endl;
129 
131  << "All boundaries will be approximated using wall-type patches. "
132  << "This may cause your" << nl
133  << " final case to run differently. "
134  << "Create your mesh first for improved performance"
135  << endl;
136 
137  const dictionary& boundaryFieldDict =
138  fieldDict.subDict("boundaryField");
139 
140  for (const entry& e : boundaryFieldDict)
141  {
142  const word type(e.dict().get<word>("type"));
143 
145  {
146  if (!constraintPatches.found(type))
147  {
148  ++nPatchWithFace_;
149  dictionary simplifiedEntries;
150  simplifiedEntries.add("startFace", 0);
151  simplifiedEntries.add("nFaces", 1);
152  simplifiedEntries.add("type", "wall"); // default to wall
153 
154  patchEntries_.add(e.keyword(), simplifiedEntries);
155  }
156  }
157  else
158  {
159  Info<< "Ignoring unknown patch type " << type << endl;
160  }
161  }
162 
163  return false;
164  }
165 }
166 
167 
168 void Foam::simplifiedMeshes::columnFvMeshInfo::initialise(const Time& runTime)
169 {
170  DebugInfo << "Constructing 1-D mesh" << nl << endl;
171 
172  // Read patches - filter out proc patches for parallel runs
173  createFromMesh_ = setPatchEntries(runTime);
174 
175  const label nPatch = patchEntries_.size();
176 
177  DebugPout << "Read " << nPatch << " patches" << endl;
178 
179  /*
180  3 ---- 7
181  f5 |\ |\ f2
182  | | 2 ---- 6 \
183  | 0 |--- 4 | \
184  | \| \| f3
185  f4 1 ---- 5
186 
187  f0 ----- f1
188  */
189 
190  // Create mesh with nPatchWithFace hex cells
191  // - hex face 1: set internal face to link to next hex cell
192  // - hex face 2,3,4,5: set to boundary condition
193  //
194  // TODO: Coupled patches:
195  // - separated/collocated cyclic - faces 2 and 3
196  // - rotational cyclic - convert to separated and warn not handled?
197  // - proc patches - faces need to be collocated?
198 
199  points1D_.setSize(nPatchWithFace_*4 + 4);
200  faces1D_.setSize(nPatchWithFace_*5 + 1);
201 
202  owner1D_.setSize(faces1D_.size(), label(-1));
203  neighbour1D_.setSize(owner1D_.size(), label(-1));
204 
205  vector dx(Zero);
206  {
207  // Determine the mesh bounds
208  IOobject pointsIO
209  (
210  "points",
211  localInstance_,
212  regionPrefix_ + polyMesh::meshSubDir,
213  runTime,
216  false
217  );
218 
219  scalar dxi = 0;
220  scalar dyi = 0;
221  scalar dzi = 0;
222  point origin(Zero);
223 
224  if (pointsIO.typeHeaderOk<vectorIOField>(true))
225  {
226  const pointIOField meshPoints(pointsIO);
227 
228  boundBox meshBb(meshPoints, true);
229 
230  Info<< "Mesh bounds: " << meshBb << endl;
231 
232  origin = meshBb.min();
233  vector span = meshBb.span();
234  dxi = span.x()/scalar(nPatchWithFace_);
235  dyi = span.y();
236  dzi = span.z();
237  }
238  else
239  {
240  scalar Lref = GREAT;
241  origin = point(-Lref, -Lref, -Lref);
242  dxi = 2.0*Lref/scalar(nPatchWithFace_);
243  dyi = Lref;
244  dzi = Lref;
245  }
246 
247  dx = vector(dxi, 0, 0);
248  const vector dy(0, dyi, 0);
249  const vector dz(0, 0, dzi);
250 
251  // End face
252  points1D_[0] = origin;
253  points1D_[1] = origin + dy;
254  points1D_[2] = origin + dy + dz;
255  points1D_[3] = origin + dz;
256  }
257 
258  label n = 4;
259  for (label i = 1; i <= nPatchWithFace_; ++i)
260  {
261  const vector idx(i*dx);
262  points1D_[i*n] = points1D_[0] + idx;
263  points1D_[i*n + 1] = points1D_[1] + idx;
264  points1D_[i*n + 2] = points1D_[2] + idx;
265  points1D_[i*n + 3] = points1D_[3] + idx;
266  }
267 
268  if (debug) Pout<< "points:" << points1D_ << endl;
269 
270  label facei = 0;
271 
272  // Internal faces first
273  for (label i = 0; i < nPatchWithFace_ - 1; ++i)
274  {
275  label o = i*4;
276  faces1D_[facei] = face({4 + o, 5 + o, 6 + o, 7 + o});
277  owner1D_[facei] = i;
278  neighbour1D_[facei] = i + 1;
279  ++facei;
280  }
281 
282  // Boundary conditions
283  for (label i = 0; i < nPatchWithFace_; ++i)
284  {
285  label o = i*4;
286  faces1D_[facei] = face({0 + o, 4 + o, 7 + o, 3 + o});
287  owner1D_[facei] = i;
288  ++facei;
289 
290  faces1D_[facei] = face({0 + o, 1 + o, 5 + o, 4 + o});
291  owner1D_[facei] = i;
292  ++facei;
293 
294  faces1D_[facei] = face({1 + o, 2 + o, 6 + o, 5 + o});
295  owner1D_[facei] = i;
296  ++facei;
297 
298  faces1D_[facei] = face({3 + o, 7 + o, 6 + o, 2 + o});
299  owner1D_[facei] = i;
300  ++facei;
301  }
302  {
303  // End caps
304  faces1D_[facei] = face({0, 3, 2, 1});
305  owner1D_[facei] = 0;
306  ++facei;
307 
308  label o = 4*nPatchWithFace_;
309  faces1D_[facei] = face({0 + o, 1 + o, 2 + o, 3 + o});
310  owner1D_[facei] = nPatchWithFace_ - 1;
311  ++facei;
312  }
313 
314  DebugPout
315  << "faces:" << faces1D_ << nl
316  << "owner:" << owner1D_ << nl
317  << "neighbour:" << neighbour1D_
318  << endl;
319 }
320 
321 
322 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
323 
325 (
326  fvMesh& mesh
327 ) const
328 {
329  const label nPatch = patchEntries_.size();
330 
331  List<polyPatch*> patches(nPatch + 1);
332 
333  label nInternalFace = nPatchWithFace_ - 1;
334  label startFace = nInternalFace;
335  label entryi = 0;
336  for (const entry& e : patchEntries_)
337  {
338  // Re-create boundary types, but reset nFaces and startFace settings
339  dictionary patchDict = e.dict();
340  const word& patchName = e.keyword();
341 
342  DebugPout << "Setting " << patchName << endl;
343 
344  label nFaces0 = patchDict.get<label>("nFaces");
345 
346  if (nFaces0)
347  {
348  // Only set to 4 faces if there were faces in the original patch
349  nFaces0 = 4;
350  patchDict.set("nFaces", nFaces0);
351  }
352 
353  patchDict.set("startFace", startFace);
354  patches[entryi] =
356  (
357  patchName,
358  patchDict,
359  entryi,
360  mesh.boundaryMesh()
361  ).ptr();
362 
363  ++entryi;
364  startFace += nFaces0;
365  }
366 
367  patches.last() = new emptyPolyPatch
368  (
369  typeName + ":default", // name
370  2, // number of faces
371  nInternalFace + 4*nPatchWithFace_, // start face
372  nPatch - 1, // index in boundary list
373  mesh.boundaryMesh(), // polyBoundaryMesh
374  emptyPolyPatch::typeName // patchType
375  );
376 
377  mesh.addFvPatches(patches);
378 
379  if (debug)
380  {
381  Pout<< "patches:" << nl << mesh.boundaryMesh() << endl;
382  }
383 }
384 
385 
387 {
388  if (createFromMesh_)
389  {
390  // Initialise the zones
391  initialiseZone<pointZoneMesh>
392  (
393  "point",
394  localInstance_,
395  mesh.pointZones()
396  );
397  initialiseZone<faceZoneMesh>("face", localInstance_, mesh.faceZones());
398  initialiseZone<cellZoneMesh>("cell", localInstance_, mesh.cellZones());
399  }
400 }
401 
402 
403 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
404 
406 (
407  const Time& runTime,
408  const word& regionName
409 )
410 :
411  regionName_(regionName),
412  regionPrefix_
413  (
414  regionName_ == polyMesh::defaultRegion
415  ? ""
416  : regionName_ + '/'
417  ),
418  localInstance_
419  (
420  runTime.findInstance
421  (
422  regionPrefix_ + polyMesh::meshSubDir,
423  "boundary",
425  )
426  ),
427  createFromMesh_(false),
428  points1D_(),
429  faces1D_(),
430  owner1D_(),
431  neighbour1D_(),
432  patchEntries_(),
433  nPatchWithFace_(0)
434 {
435  initialise(runTime);
436 
437  // Dummy zones and sets created on demand
438  // Note: zones can be updated post-construction
441 }
442 
443 
445 (
446  const Time& runTime,
447  const word& regionName
448 )
449 :
452  (
453  IOobject
454  (
455  regionName,
456  runTime.constant(),
457  runTime,
458  IOobject::NO_READ, // Do not read any existing mesh
460  ),
461  std::move(points1D_),
462  std::move(faces1D_),
463  std::move(owner1D_),
464  std::move(neighbour1D_)
465  )
466 {
467  // Workaround to read fvSchemes and fvSolution after setting NO_READ
468  // when creating the mesh
469  {
471  fvSchemes::read();
474  }
475 
476  // Add the patches
477  addLocalPatches(*this);
478 
479  // Add the zones if constructed from mesh
480  initialiseZones(*this);
481 
482  if (debug)
483  {
484  setInstance(runTime.timeName());
486  }
487 }
488 
489 
490 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::entry
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:67
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
Foam::vectorIOField
IOField< vector > vectorIOField
vectorField with IO.
Definition: vectorIOField.H:44
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::simplifiedMeshes::columnFvMeshInfo::addLocalPatches
void addLocalPatches(fvMesh &mesh) const
Add the patches to the mesh.
Definition: columnFvMesh.C:325
Foam::polyMesh::defaultRegion
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:318
topoSet.H
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::polyMesh::meshSubDir
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:321
Foam::simplifiedMeshes::addToRunTimeSelectionTable
addToRunTimeSelectionTable(simplifiedDynamicFvMeshBase, simplifiedstaticFvMesh, time)
Foam::topoSet::disallowGenericSets
static int disallowGenericSets
Debug switch to disallow the use of generic sets.
Definition: topoSet.H:120
IOobjectList.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:107
Foam::dictionary::set
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition: dictionary.C:780
meshBb
List< treeBoundBox > meshBb(1, treeBoundBox(boundBox(coarseMesh.points(), false)).extend(rndGen, 1e-3))
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
polyBoundaryMeshEntries.H
Foam::simplifiedMeshes::columnFvMeshInfo::initialiseZones
void initialiseZones(fvMesh &mesh)
Initialise zones if constructed from mesh.
Definition: columnFvMesh.C:386
Foam::simplifiedMeshes::columnFvMeshInfo::patchEntries_
dictionary patchEntries_
Dictionary of patch information.
Definition: columnFvMesh.H:108
columnFvMesh.H
n
label n
Definition: TABSMDCalcMethod2.H:31
regionName
Foam::word regionName
Definition: createNamedDynamicFvMesh.H:1
Foam::simplifiedMeshes::columnFvMeshInfo::regionName_
const word regionName_
Region of existing mesh.
Definition: columnFvMesh.H:78
Foam::pointIOField
vectorIOField pointIOField
pointIOField is a vectorIOField.
Definition: pointIOField.H:44
Foam::regIOobject::write
virtual bool write(const bool valid=true) const
Write using setting from DB.
Definition: regIOobjectWrite.C:132
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::IOobject::READ_IF_PRESENT
Definition: IOobject.H:187
Foam::simplifiedFvMesh::fvPatchFieldExists
static bool fvPatchFieldExists(const word &patchType)
Definition: simplifiedFvMesh.C:43
Foam::solution::read
bool read()
Read the solution dictionary.
Definition: solution.C:367
Foam::simplifiedMeshes::columnFvMeshInfo::columnFvMeshInfo
columnFvMeshInfo(const Time &runTime, const word &regionName)
Definition: columnFvMesh.C:406
Foam::polyPatch::constraintTypes
static wordList constraintTypes()
Return a list of all the constraint patch types.
Definition: polyPatch.C:287
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::simplifiedMeshes::columnFvMeshInfo::localInstance_
const word localInstance_
Location of existing mesh (if present)
Definition: columnFvMesh.H:84
Foam::polyPatch::New
static autoPtr< polyPatch > New(const word &patchType, const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm)
Return pointer to a new patch created on freestore from components.
Definition: polyPatchNew.C:35
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::simplifiedMeshes::defineTypeNameAndDebug
defineTypeNameAndDebug(simplifiedDynamicFvMeshBase, 0)
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
emptyPolyPatch.H
DebugPout
#define DebugPout
Report an information message using Foam::Pout.
Definition: messageStream.H:393
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::IOobject::readOpt
readOption readOpt() const noexcept
The read option.
Definition: IOobjectI.H:164
Foam::emptyPolyPatch
Empty front and back plane patch. Used for 2-D geometries.
Definition: emptyPolyPatch.H:50
vectorIOField.H
Foam::simplifiedFvMesh
Functions to generate simplified finite volume meshes.
Definition: simplifiedFvMesh.H:52
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
DebugInfo
#define DebugInfo
Report an information message using Foam::Info.
Definition: messageStream.H:382
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
Foam::type
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:590
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::simplifiedMeshes::columnFvMeshInfo
Definition: columnFvMesh.H:53
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::simplifiedMeshes::columnFvMeshInfo::regionPrefix_
const fileName regionPrefix_
Additional prefix for region. Empty if default region.
Definition: columnFvMesh.H:81
Foam::wordHashSet
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:77
Foam::ZoneMesh< cellZone, polyMesh >::disallowGenericZones
static int disallowGenericZones
Debug switch to disallow the use of generic zones.
Definition: ZoneMesh.H:106
Foam::dictionary::add
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:640
Foam::schemesLookup::read
bool read()
Read schemes from IOdictionary, respects the "select" keyword.
Definition: schemesLookup.C:160
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::IOobject::NO_READ
Definition: IOobject.H:188
Foam::simplifiedMeshes::columnFvMesh::columnFvMesh
columnFvMesh(const Time &runTime, const word &regionName=polyMesh::defaultRegion)
Constructor.
Definition: columnFvMesh.C:445
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
fieldDictionary.H
Foam::IOobject::MUST_READ
Definition: IOobject.H:185
Foam::simplifiedMeshes::columnFvMeshInfo::nPatchWithFace_
label nPatchWithFace_
Number of patches with at least 1 local face.
Definition: columnFvMesh.H:111