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-2022 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,
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  polyMesh::meshDir(regionName_),
213  runTime,
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  localInstance_
413  (
414  runTime.findInstance
415  (
416  polyMesh::meshDir(regionName_),
417  "boundary",
418  IOobject::READ_IF_PRESENT
419  )
420  ),
421  createFromMesh_(false),
422  points1D_(),
423  faces1D_(),
424  owner1D_(),
425  neighbour1D_(),
426  patchEntries_(),
427  nPatchWithFace_(0)
428 {
429  initialise(runTime);
430 
431  // Dummy zones and sets created on demand
432  // Note: zones can be updated post-construction
435 }
436 
437 
439 (
440  const Time& runTime,
441  const word& regionName
442 )
443 :
446  (
447  IOobject
448  (
449  regionName,
450  runTime.constant(),
451  runTime,
452  IOobject::NO_READ, // Do not read any existing mesh
453  IOobject::NO_WRITE
454  ),
455  std::move(points1D_),
456  std::move(faces1D_),
457  std::move(owner1D_),
458  std::move(neighbour1D_)
459  )
460 {
461  // Workaround to read fvSchemes and fvSolution after setting NO_READ
462  // when creating the mesh
463  {
465  fvSchemes::read();
468  }
469 
470  // Add the patches
471  addLocalPatches(*this);
472 
473  // Add the zones if constructed from mesh
474  initialiseZones(*this);
475 
476  if (debug)
477  {
478  setInstance(runTime.timeName());
480  }
481 }
482 
483 
484 // ************************************************************************* //
readOption readOpt() const noexcept
Get the read option.
defineTypeNameAndDebug(simplifiedDynamicFvMeshBase, 0)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
const word localInstance_
Location of existing mesh (if present)
Definition: columnFvMesh.H:87
columnFvMesh(const Time &runTime, const word &regionName=polyMesh::defaultRegion)
Constructor.
Definition: columnFvMesh.C:432
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
const word & regionName() const
The mesh region name or word::null if polyMesh::defaultRegion.
Definition: polyMesh.C:847
bool read()
Read the solution dictionary.
Definition: solution.C:442
vectorIOField pointIOField
pointIOField is a vectorIOField.
Definition: pointIOField.H:38
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
static int disallowGenericSets
Debug switch to disallow the use of generic sets.
Definition: topoSet.H:134
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:625
Ignore writing from objectRegistry::writeObject()
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
Functions to generate simplified finite volume meshes.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
Macros for easy insertion into run-time selection tables.
addToRunTimeSelectionTable(simplifiedDynamicFvMeshBase, simplifiedstaticFvMesh, time)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
static bool fvPatchFieldExists(const word &patchType)
Helper function to see if the patch type exists in the run-time selection tables. ...
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
A class for handling words, derived from Foam::string.
Definition: word.H:63
virtual bool write(const bool writeOnProc=true) const
Write using setting from DB.
Vector< scalar > vector
Definition: vector.H:57
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:73
#define DebugInfo
Report an information message using Foam::Info.
void addLocalPatches(fvMesh &mesh) const
Add the patches to the mesh.
Definition: columnFvMesh.C:318
int debug
Static debugging option.
Empty front and back plane patch. Used for 2-D geometries.
const word regionName_
Region of existing mesh.
Definition: columnFvMesh.H:82
columnFvMeshInfo(const Time &runTime, const word &regionName)
Definition: columnFvMesh.C:399
static wordList constraintTypes()
Return a list of all the constraint patch types.
Definition: polyPatch.C:280
vector point
Point is a vector.
Definition: point.H:37
label nPatchWithFace_
Number of patches with at least 1 local face.
Definition: columnFvMesh.H:128
void setInstance(const fileName &instance, const IOobjectOption::writeOption wOpt=IOobject::AUTO_WRITE)
Set the instance for mesh files.
Definition: polyMeshIO.C:29
#define WarningInFunction
Report a warning using Foam::Warning.
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
fileName meshDir() const
Return the local mesh directory (dbDir()/meshSubDir)
Definition: polyMesh.C:841
const polyBoundaryMesh & patches
#define DebugPout
Report an information message using Foam::Pout.
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
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:28
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition: dictionary.C:765
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
static int disallowGenericZones
Debug switch to disallow the use of generic zones.
Definition: ZoneMesh.H:136
dictionary patchEntries_
Dictionary of patch information.
Definition: columnFvMesh.H:123
IOField< vector > vectorIOField
IO for a Field of vector.
Definition: vectorIOField.H:32
void initialiseZones(fvMesh &mesh)
Initialise zones if constructed from mesh.
Definition: columnFvMesh.C:379
static int debug
Debug switch.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Do not request registration (bool: false)
List< treeBoundBox > meshBb(1, treeBoundBox(coarseMesh.points()).extend(rndGen, 1e-3))
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
bool read()
Read schemes from IOdictionary, respects the "select" keyword.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127