extrudePatchMesh.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2020-2024 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "extrudePatchMesh.H"
30 
31 #include "createShellMesh.H"
32 #include "polyTopoChange.H"
33 #include "wallPolyPatch.H"
34 #include "emptyPolyPatch.H"
35 #include "wedgePolyPatch.H"
36 #include "unitConversion.H"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(extrudePatchMesh, 0);
43 }
44 
45 
46 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
47 
48 Foam::extrudePatchMesh::extrudePatchMesh
49 (
50  const word& regionName,
51  const fvMesh& mesh,
52  const fvPatch& p,
53  const dictionary& dict
54 )
55 :
56  fvMesh
57  (
58  IOobject
59  (
60  regionName,
61  mesh.facesInstance(),
62  mesh,
63  IOobject::READ_IF_PRESENT,
64  IOobject::NO_WRITE,
65  IOobject::REGISTER
66  ),
67  Zero,
68  false
69  ),
70  extrudedPatch_(p.patch()),
71  dict_(dict)
72 {}
73 
74 
75 Foam::extrudePatchMesh::extrudePatchMesh
76 (
77  const fvMesh& mesh,
78  const fvPatch& p,
79  const dictionary& dict,
80  const word& regionName,
81  const polyPatchList& regionPatches
82 )
83 :
85 {
86  extrudeMesh(regionPatches);
87 }
88 
89 
90 Foam::extrudePatchMesh::extrudePatchMesh
91 (
92  const fvMesh& mesh,
93  const fvPatch& p,
94  const dictionary& dict,
95  const word& regionName,
96  const List<polyPatch*>& regionPatches
97 )
98 :
100 {
101  // Acquire ownership of the pointers
102  polyPatchList plist(const_cast<List<polyPatch*>&>(regionPatches));
103 
104  extrudeMesh(plist);
105 }
106 
107 
108 Foam::extrudePatchMesh::extrudePatchMesh
109 (
110  const fvMesh& mesh,
111  const fvPatch& p,
112  const dictionary& dict,
113  const word& regionName
114 )
115 :
117 {
118  polyPatchList regionPatches(3);
119  List<dictionary> dicts(regionPatches.size());
120  List<word> patchNames(regionPatches.size());
121  List<word> patchTypes(regionPatches.size());
122 
123  dicts[bottomPatchID] = dict_.subDict("bottomCoeffs");
124  dicts[sidePatchID] = dict_.subDict("sideCoeffs");
125  dicts[topPatchID] = dict_.subDict("topCoeffs");
126 
127  forAll(dicts, patchi)
128  {
129  dicts[patchi].readEntry("name", patchNames[patchi]);
130  dicts[patchi].readEntry("type", patchTypes[patchi]);
131  }
132 
133  forAll(regionPatches, patchi)
134  {
135  dictionary& patchDict = dicts[patchi];
136  patchDict.set("nFaces", 0);
137  patchDict.set("startFace", 0);
138 
139  regionPatches.set
140  (
141  patchi,
143  (
144  patchNames[patchi],
145  patchDict,
146  patchi,
147  mesh.boundaryMesh()
148  )
149  );
150  }
151 
152  extrudeMesh(regionPatches);
153 }
154 
155 
156 void Foam::extrudePatchMesh::extrudeMesh(const polyPatchList& regionPatches)
157 {
158  if (this->boundaryMesh().empty())
159  {
160  const bool columnCells = dict_.get<bool>("columnCells");
161  scalar featAngleCos = -GREAT;
162  scalar featAngle = -1;
163  if (dict_.readIfPresent("featureAngle", featAngle))
164  {
165  featAngleCos = Foam::cos(degToRad(featAngle));
166  }
167 
168  bitSet nonManifoldEdge(extrudedPatch_.nEdges());
169  for (label edgeI = 0; edgeI < extrudedPatch_.nInternalEdges(); edgeI++)
170  {
171  if (columnCells)
172  {
173  nonManifoldEdge.set(edgeI);
174  }
175  else
176  {
177  const auto& fcs = extrudedPatch_.edgeFaces()[edgeI];
178  if (fcs.size() > 2)
179  {
180  // TBD: issue #2780 : non-manifold edges get seen as
181  // internal.
182  // This bit of code can be removed once #2780 is solved.
183  nonManifoldEdge.set(edgeI);
184  }
185  else if (fcs.size() == 2 && featAngleCos >= -1)
186  {
187  const auto& n = extrudedPatch_.faceNormals();
188  if ((n[fcs[0]] & n[fcs[1]]) < featAngleCos)
189  {
190  nonManifoldEdge.set(edgeI);
191  }
192  }
193  }
194  }
195 
196  autoPtr<extrudeModel> model_(extrudeModel::New(dict_));
197 
198  faceList pointGlobalRegions;
199  faceList pointLocalRegions;
200  labelList localToGlobalRegion;
201 
202  const primitiveFacePatch pp
203  (
204  extrudedPatch_, extrudedPatch_.points()
205  );
206 
208  (
209  this->globalData(),
210  pp,
211  nonManifoldEdge,
212  false,
213 
214  pointGlobalRegions,
215  pointLocalRegions,
216  localToGlobalRegion
217  );
218 
219 
220  // Per local region an originating point
221  labelList localRegionPoints(localToGlobalRegion.size());
222  forAll(pointLocalRegions, facei)
223  {
224  const face& f = extrudedPatch_.localFaces()[facei];
225  const face& pRegions = pointLocalRegions[facei];
226  forAll(pRegions, fp)
227  {
228  localRegionPoints[pRegions[fp]] = f[fp];
229  }
230  }
231 
232  // Calculate region normals by reducing local region normals
233  pointField localRegionNormals(localToGlobalRegion.size());
234  {
235  pointField localSum(localToGlobalRegion.size(), Zero);
236 
237  forAll(pointLocalRegions, facei)
238  {
239  const face& pRegions = pointLocalRegions[facei];
240  forAll(pRegions, fp)
241  {
242  label localRegionI = pRegions[fp];
243  localSum[localRegionI] +=
244  extrudedPatch_.faceNormals()[facei];
245  }
246  }
247 
248  Map<point> globalSum(2*localToGlobalRegion.size());
249 
250  forAll(localSum, localRegionI)
251  {
252  label globalRegionI = localToGlobalRegion[localRegionI];
253  globalSum.insert(globalRegionI, localSum[localRegionI]);
254  }
255 
256  // Reduce
257  Pstream::mapCombineReduce(globalSum, plusEqOp<point>());
258 
259  forAll(localToGlobalRegion, localRegionI)
260  {
261  label globalRegionI = localToGlobalRegion[localRegionI];
262  localRegionNormals[localRegionI] = globalSum[globalRegionI];
263  }
264  localRegionNormals /= mag(localRegionNormals);
265  }
266 
267 
268  // Per local region an extrusion direction
269  vectorField firstDisp(localToGlobalRegion.size());
270  forAll(firstDisp, regionI)
271  {
272  //const point& regionPt = regionCentres[regionI];
273  const point& regionPt = extrudedPatch_.points()
274  [
275  extrudedPatch_.meshPoints()
276  [
277  localRegionPoints[regionI]
278  ]
279  ];
280  const vector& n = localRegionNormals[regionI];
281  firstDisp[regionI] = model_()(regionPt, n, 1) - regionPt;
282  }
283 
284  const label nNewPatches = regionPatches.size();
285 
286  // Extrude engine
287  createShellMesh extruder
288  (
289  pp,
290  pointLocalRegions,
291  localRegionPoints
292  );
293  this->clearOut();
294  this->removeFvBoundary();
295  // Make sure the patches index the new mesh
296  polyPatchList newRegionPatches(regionPatches.size());
297  forAll(regionPatches, patchi)
298  {
299  newRegionPatches.set
300  (
301  patchi,
302  regionPatches[patchi].clone(this->boundaryMesh())
303  );
304  }
305  this->addFvPatches(newRegionPatches, true);
306 
307 
308  // At this point we have a valid mesh with 3 patches and zero cells.
309  // Determine:
310  // - per face the top and bottom patch (topPatchID, bottomPatchID)
311  // - per edge, per face on edge the side patch (edgePatches)
312  labelListList edgePatches(extrudedPatch_.nEdges());
313  forAll(edgePatches, edgeI)
314  {
315  const labelList& eFaces = extrudedPatch_.edgeFaces()[edgeI];
316 
317  if (eFaces.size() != 2 || nonManifoldEdge.test(edgeI))
318  {
319  edgePatches[edgeI].setSize(eFaces.size(), sidePatchID);
320  }
321  }
322 
323  polyTopoChange meshMod(nNewPatches);
324 
325  extruder.setRefinement
326  (
327  firstDisp, // first displacement
328  model_().expansionRatio(),
329  model_().nLayers(), // nLayers
330  labelList(extrudedPatch_.size(), topPatchID),
331  labelList(extrudedPatch_.size(), bottomPatchID),
332  edgePatches,
333  meshMod
334  );
335 
336  autoPtr<mapPolyMesh> map = meshMod.changeMesh
337  (
338  *this, // mesh to change
339  false // inflate
340  );
341 
342  // Update numbering on extruder.
343  extruder.updateMesh(map());
344 
345  this->setInstance(this->thisDb().time().constant());
346  this->write();
347  }
348 }
349 
350 
351 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:119
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:130
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
Unit conversion functions.
wordList patchTypes(nPatches)
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:70
Mesh at a patch created on the fly. The following entry should be used on the field boundary dictiona...
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:441
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:400
dictionary()
Default construct, a top-level empty dictionary.
Definition: dictionary.C:68
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
PtrList< polyPatch > polyPatchList
Store lists of polyPatch as a PtrList.
Definition: polyPatch.H:56
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
dynamicFvMesh & mesh
dimensionedScalar cos(const dimensionedScalar &ds)
A class for handling words, derived from Foam::string.
Definition: word.H:63
wordList patchNames(nPatches)
static void mapCombineReduce(Container &values, CombineOp cop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Forwards to Pstream::mapReduce with an in-place cop.
Vector< scalar > vector
Definition: vector.H:57
static void calcPointRegions(const globalMeshData &globalData, const primitiveFacePatch &patch, const bitSet &nonManifoldEdge, const bool syncNonCollocated, faceList &pointGlobalRegions, faceList &pointLocalRegions, labelList &localToGlobalRegion)
Helper: calculate point regions. The point region is the.
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
static autoPtr< extrudeModel > New(const dictionary &dict)
Select null constructed.
PrimitivePatch< List< face >, const pointField & > primitiveFacePatch
A PrimitivePatch with List storage for the faces, const reference for the point field.
Expression::UniformListWrap< scalar > constant
Wrap of constant as a list expression.
decomposeUsingBbs false
Use bounding boxes (default) or unique decomposition of triangles (i.e. do not duplicate triangles) ...
vector point
Point is a vector.
Definition: point.H:37
bool set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:468
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: PtrList.H:56
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
const std::string patch
OpenFOAM patch number as a std::string.
label n
Field< vector > vectorField
Specialisation of Field<T> for vector.
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
List< label > labelList
A List of labels.
Definition: List.H:61
volScalarField & p
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
void setSize(label n)
Alias for resize()
Definition: List.H:535
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127