refineImmersedBoundaryMesh.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | foam-extend: Open Source CFD
4  \\ / O peration | Version: 3.2
5  \\ / A nd | Web: http://www.foam-extend.org
6  \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9  This file is part of foam-extend.
10 
11  foam-extend is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by the
13  Free Software Foundation, either version 3 of the License, or (at your
14  option) any later version.
15 
16  foam-extend is distributed in the hope that it will be useful, but
17  WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
28 #include "volFields.H"
29 #include "surfaceFields.H"
30 #include "plane.H"
31 #include "wedgePolyPatch.H"
32 #include "multiDirRefinement.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 template<>
37 const char*
39 ::names[] =
40 {
41  "undefined",
42  "ibCells",
43  "ibCellCells",
44  "ibCellCellFaces"
45 };
46 
47 
50 
51 
52 
53 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
54 
56 (
57  labelHashSet& refCellSet
58 ) const
59 {
60  Info<< "Adding ibCells for refinement" << endl;
61 
62  // Insert immersed boundary cells from all immersed boundary patches
63  forAll (mesh_.boundary(), patchI)
64  {
65  if (isA<immersedBoundaryFvPatch>(mesh_.boundary()[patchI]))
66  {
67  Info<< "Found immersed boundary patch " << patchI
68  << " named " << mesh_.boundary()[patchI].name()
69  << endl;
70 
71  const immersedBoundaryFvPatch& ibPatch =
72  refCast<const immersedBoundaryFvPatch>
73  (
74  mesh_.boundary()[patchI]
75  );
76 
77  const labelList& c = ibPatch.ibCells();
78 
79  forAll (c, cI)
80  {
81  if (!refCellSet.found(c[cI]))
82  {
83  refCellSet.insert(c[cI]);
84  }
85  }
86  }
87  }
88 }
89 
90 
92 (
93  labelHashSet& refCellSet
94 ) const
95 {
96  Info<< "Adding ibCellCells for refinement" << endl;
97 
98  // Insert immersed boundary cells from all immersed boundary patches
99  forAll (mesh_.boundary(), patchI)
100  {
101  if (isA<immersedBoundaryFvPatch>(mesh_.boundary()[patchI]))
102  {
103  const immersedBoundaryFvPatch& ibPatch =
104  refCast<const immersedBoundaryFvPatch>
105  (
106  mesh_.boundary()[patchI]
107  );
108 
109  const labelListList& cc = ibPatch.ibCellCells();
110 
111  forAll (cc, cellI)
112  {
113  const labelList& curCells = cc[cellI];
114 
115  forAll (curCells, cI)
116  {
117  if (!refCellSet.found(curCells[cI]))
118  {
119  refCellSet.insert(curCells[cI]);
120  }
121  }
122  }
123  }
124  }
125 }
126 
127 
129 (
130  labelHashSet& refCellSet
131 ) const
132 {
133  Info<< "Adding ibCellCellFaces for refinement" << endl;
134 
135  const unallocLabelList& owner = mesh_.owner();
136  const unallocLabelList& neighbour = mesh_.neighbour();
137 
138  // Insert immersed boundary cells from all immersed boundary patches
139  forAll (mesh_.boundary(), patchI)
140  {
141  if (isA<immersedBoundaryFvPatch>(mesh_.boundary()[patchI]))
142  {
143  const immersedBoundaryFvPatch& ibPatch =
144  refCast<const immersedBoundaryFvPatch>
145  (
146  mesh_.boundary()[patchI]
147  );
148 
149  const scalarField& gammaExtI = ibPatch.gammaExt().internalField();
150 
151  const labelList& ibInsideFaces = ibPatch.ibInsideFaces();
152 
153  forAll (ibInsideFaces, faceI)
154  {
155  const label ownCell = owner[ibInsideFaces[faceI]];
156  const label ngbCell = neighbour[ibInsideFaces[faceI]];
157 
158  if (gammaExtI[ownCell] < SMALL)
159  {
160  if (!refCellSet.found(ownCell))
161  {
162  refCellSet.insert(ownCell);
163  }
164  }
165  else
166  {
167  if (!refCellSet.found(ngbCell))
168  {
169  refCellSet.insert(ngbCell);
170  }
171  }
172  }
173  }
174  }
175 }
176 
177 
178 // Return index of coordinate axis.
180 {
181  const scalar edgeTol = 1e-3;
182 
183  label axisIndex = -1;
184 
185  if (mag(normal & vector(1, 0, 0)) > (1 - edgeTol))
186  {
187  axisIndex = 0;
188  }
189  else if (mag(normal & vector(0, 1, 0)) > (1 - edgeTol))
190  {
191  axisIndex = 1;
192  }
193  else if (mag(normal & vector(0, 0, 1)) > (1 - edgeTol))
194  {
195  axisIndex = 2;
196  }
197 
198  return axisIndex;
199 }
200 
201 
202 //- Returns -1 or cartesian coordinate component (0=x, 1=y, 2=z) of normal
203 // in case of 2D mesh
205 {
206  const pointField& ctrs = mesh_.cellCentres();
207 
208  if (ctrs.size() < 2)
209  {
210  return -1;
211  }
212 
213  //
214  // 1. All cell centres on single plane aligned with x, y or z
215  //
216 
217  // Determine 3 points to base plane on.
218  vector vec10 = ctrs[1] - ctrs[0];
219  vec10 /= mag(vec10);
220 
221  label otherCellI = -1;
222 
223  for (label cellI = 2; cellI < ctrs.size(); cellI++)
224  {
225  vector vec(ctrs[cellI] - ctrs[0]);
226  vec /= mag(vec);
227 
228  if (mag(vec & vec10) < 0.9)
229  {
230  // ctrs[cellI] not in line with n
231  otherCellI = cellI;
232 
233  break;
234  }
235  }
236 
237  if (otherCellI == -1)
238  {
239  // Cannot find cell to make decent angle with cell0-cell1 vector.
240  // Note: what to do here? All cells (almost) in one line.
241  // Maybe 1D case?
242  return -1;
243  }
244 
245  plane cellPlane(ctrs[0], ctrs[1], ctrs[otherCellI]);
246 
247 
248  forAll (ctrs, cellI)
249  {
250  const labelList& cEdges = mesh_.cellEdges()[cellI];
251 
252  scalar minLen = GREAT;
253 
254  forAll (cEdges, i)
255  {
256  minLen = min(minLen, mesh_.edges()[cEdges[i]].mag(mesh_.points()));
257  }
258 
259  if (cellPlane.distance(ctrs[cellI]) > 1e-6*minLen)
260  {
261  // Centres not in plane
262  return -1;
263  }
264  }
265 
266  label axisIndex = axis(cellPlane.normal());
267 
268  if (axisIndex == -1)
269  {
270  return axisIndex;
271  }
272 
273 
274  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
275 
276 
277  //
278  // 2. No edges without points on boundary
279  //
280 
281  // Mark boundary points
282  boolList boundaryPoint(mesh_.allPoints().size(), false);
283 
284  forAll (patches, patchI)
285  {
286  const polyPatch& patch = patches[patchI];
287 
288  forAll (patch, patchFaceI)
289  {
290  const face& f = patch[patchFaceI];
291 
292  forAll (f, fp)
293  {
294  boundaryPoint[f[fp]] = true;
295  }
296  }
297  }
298 
299 
300  const edgeList& edges = mesh_.edges();
301 
302  forAll (edges, edgeI)
303  {
304  const edge& e = edges[edgeI];
305 
306  if (!boundaryPoint[e.start()] && !boundaryPoint[e.end()])
307  {
308  // Edge has no point on boundary.
309  return -1;
310  }
311  }
312 
313 
314  // 3. For all non-wedge patches: all faces either perp or aligned with
315  // cell-plane normal. (wedge patches already checked upon construction)
316 
317  forAll (patches, patchI)
318  {
319  const polyPatch& patch = patches[patchI];
320 
321  if (!isA<wedgePolyPatch>(patch))
322  {
323  const vectorField& n = patch.faceAreas();
324 
325  scalarField cosAngle = mag(n/mag(n) & cellPlane.normal());
326 
327  if (mag(min(cosAngle) - max(cosAngle)) > 1e-6)
328  {
329  // cosAngle should be either ~1 over all faces (2D front and
330  // back) or ~0 (all other patches perp to 2D)
331  return -1;
332  }
333  }
334  }
335 
336  return axisIndex;
337 }
338 
339 
340 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
341 
343 (
344  fvMesh& mesh
345 )
346 :
347  mesh_(mesh)
348 {}
349 
350 
351 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
352 
354 {}
355 
356 
357 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
358 
361 (
362  const ibCellCollection& collectionType
363 ) const
364 {
365  labelHashSet refCellSet;
366 
367  switch (collectionType)
368  {
369  // Note: fall-through is intentional. HJ, 25/Oct/2012
370  case IB_CELL_CELL_FACES:
371  {
372  addIbCellCellFaces(refCellSet);
373  }
374 
375  case IB_CELL_CELLS:
376  {
377  addIbCellCells(refCellSet);
378  }
379 
380  case IB_CELLS:
381  {
382  addIbCells(refCellSet);
383  }
384  break;
385 
386  default:
387  {
389  (
390  "labelList refineImmersedBoundaryMesh::refinementCells\n"
391  "(\n"
392  " const ibCellCollection& collectionType\n"
393  ") const"
394  ) << "Collection type undefined: "
395  << ibCellCollectionNames_[collectionType]
396  << abort(FatalError);
397  }
398  }
399 
400  return refCellSet.toc();
401 }
402 
403 
405 (
406  const labelList& refCells
407 ) const
408 {
409  Info << "nRefCells = " << refCells.size() << "\n" << endl;
410 
411  // Dictionary to control refinement
412  dictionary refineDict;
413 
414  // Set refinement directions based on 2D/3D
415  label axisIndex = twoDNess();
416 
417  if (axisIndex == -1)
418  {
419  Info<< "3D case; refining all directions" << nl << endl;
420 
421  wordList directions(3);
422  directions[0] = "tan1";
423  directions[1] = "tan2";
424  directions[2] = "normal";
425  refineDict.add("directions", directions);
426 
427  // Use hex cutter
428  refineDict.add("useHexTopology", "true");
429  }
430  else
431  {
432  wordList directions(2);
433 
434  if (axisIndex == 0)
435  {
436  Info<< "2D case; refining in directions y,z\n" << endl;
437  directions[0] = "tan2";
438  directions[1] = "normal";
439  }
440  else if (axisIndex == 1)
441  {
442  Info<< "2D case; refining in directions x,z\n" << endl;
443  directions[0] = "tan1";
444  directions[1] = "normal";
445  }
446  else
447  {
448  Info<< "2D case; refining in directions x,y\n" << endl;
449  directions[0] = "tan1";
450  directions[1] = "tan2";
451  }
452 
453  refineDict.add("directions", directions);
454 
455  // Use standard cutter
456  refineDict.add("useHexTopology", "false");
457  }
458 
459  refineDict.add("coordinateSystem", "global");
460 
461  dictionary coeffsDict;
462  coeffsDict.add("tan1", vector(1, 0, 0));
463  coeffsDict.add("tan2", vector(0, 1, 0));
464  refineDict.add("globalCoeffs", coeffsDict);
465 
466  refineDict.add("geometricCut", "false");
467  refineDict.add("writeMesh", "false");
468 
469  // Multi-directional refinement (does multiple iterations)
470  multiDirRefinement multiRef(mesh_, refCells, refineDict);
471 }
472 
473 
474 // ************************************************************************* //
Foam::plane::distance
scalar distance(const point &p) const
Return distance from the given point to the plane.
Definition: plane.C:317
volFields.H
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:48
Foam::plane::normal
const vector & normal() const
Return plane normal.
Definition: plane.C:248
refineImmersedBoundaryMesh.H
Foam::refineImmersedBoundaryMesh::refineMesh
void refineMesh(const labelList &refCells) const
Definition: refineImmersedBoundaryMesh.C:405
Foam::edgeList
List< edge > edgeList
Definition: edgeList.H:38
Foam::labelList
List< label > labelList
A List of labels.
Definition: labelList.H:56
Foam::polyBoundaryMesh
Foam::polyBoundaryMesh.
Definition: polyBoundaryMesh.H:60
Foam::HashTable::toc
List< Key > toc() const
Return the table of contents.
Definition: HashTable.C:201
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
wedgePolyPatch.H
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
multiDirRefinement.H
Foam::refineImmersedBoundaryMesh::addIbCellCellFaces
void addIbCellCellFaces(labelHashSet &refCellSet) const
Add ibCellCellFaces for refinement.
Definition: refineImmersedBoundaryMesh.C:129
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
surfaceFields.H
Foam::surfaceFields.
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::directions
Set of directions for each cell in the mesh. Either uniform and size=1 or one set of directions per c...
Definition: directions.H:63
Foam::HashSet< label, Hash< label > >
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:49
Foam::plane
Geometric class that creates a 2D plane and can return the intersection point between a line and the ...
Definition: plane.H:60
Foam::refineImmersedBoundaryMesh::axis
label axis(const vector &normal) const
From refineMesh application.
Definition: refineImmersedBoundaryMesh.C:179
Foam::refineImmersedBoundaryMesh::ibCellCollection
ibCellCollection
Cell collection method.
Definition: refineImmersedBoundaryMesh.H:55
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::immersedBoundaryFvPatch::ibCells
const labelList & ibCells() const
Return list of fluid cells next to immersed boundary (IB cells)
Definition: immersedBoundaryFvPatch.C:2289
plane.H
Foam::immersedBoundaryFvPatch
Immersed boundary FV patch.
Definition: immersedBoundaryFvPatch.H:66
Foam::refineImmersedBoundaryMesh::refineImmersedBoundaryMesh
refineImmersedBoundaryMesh(const refineImmersedBoundaryMesh &)
Disallow default bitwise copy construct.
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
Foam::refineImmersedBoundaryMesh::ibCellCollectionNames_
static const NamedEnum< ibCellCollection, 4 > ibCellCollectionNames_
Projection method names.
Definition: refineImmersedBoundaryMesh.H:64
Foam::GeometricField::internalField
InternalField & internalField()
Return internal field.
Definition: GeometricField.C:724
Foam::multiDirRefinement
Does multiple pass refinement to refine cells in multiple directions.
Definition: multiDirRefinement.H:74
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:137
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam::HashTable::found
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:109
Foam::refineImmersedBoundaryMesh::refinementCells
labelList refinementCells(const ibCellCollection &collectionType) const
Return list of cells for refinement based on specifie collection.
Definition: refineImmersedBoundaryMesh.C:361
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::e
const double e
Elementary charge.
Definition: doubleFloat.H:94
Foam::boolList
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
Foam::refineImmersedBoundaryMesh::twoDNess
label twoDNess() const
From refineMesh application.
Definition: refineImmersedBoundaryMesh.C:204
Foam::immersedBoundaryFvPatch::gammaExt
const volScalarField & gammaExt() const
Get extended flud cells indicator, including live and IB cells.
Definition: immersedBoundaryFvPatch.C:2267
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::refineImmersedBoundaryMesh::addIbCells
void addIbCells(labelHashSet &refCellSet) const
Add ibCells for refinement.
Definition: refineImmersedBoundaryMesh.C:56
Foam::immersedBoundaryFvPatch::ibCellCells
const labelListList & ibCellCells() const
Return IB cell extended stencil.
Definition: immersedBoundaryFvPatch.C:2400
f
labelList f(nPoints)
Foam::Vector< scalar >
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::polyPatch::faceAreas
const vectorField::subField faceAreas() const
Return face normals.
Definition: polyPatch.C:314
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:60
Foam::refineImmersedBoundaryMesh::~refineImmersedBoundaryMesh
~refineImmersedBoundaryMesh()
Destructor.
Definition: refineImmersedBoundaryMesh.C:353
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:116
Foam::immersedBoundaryFvPatch::ibInsideFaces
const labelList & ibInsideFaces() const
Return list of fluid faces for which one neighbour is an.
Definition: immersedBoundaryFvPatch.C:2333
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
patches
patches[0]
Definition: createSingleCellMesh.H:36
immersedBoundaryFvPatch.H
FatalErrorIn
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:313
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::refineImmersedBoundaryMesh::addIbCellCells
void addIbCellCells(labelHashSet &refCellSet) const
Add ibCellCells for refinement.
Definition: refineImmersedBoundaryMesh.C:92
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::min
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::dictionary::add
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:729
Foam::NamedEnum
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:52
normal
A normal distribution model.