cellVolumeWeightMethod.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 | Copyright (C) 2013-2014 OpenFOAM Foundation
6  \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "cellVolumeWeightMethod.H"
27 #include "indexedOctree.H"
28 #include "treeDataCell.H"
30 
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
35  defineTypeNameAndDebug(cellVolumeWeightMethod, 0);
37  (
38  meshToMeshMethod,
39  cellVolumeWeightMethod,
40  components
41  );
42 }
43 
44 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
45 
47 (
48  const labelList& srcCellIDs,
49  const boolList& mapFlag,
50  const label startSeedI,
51  label& srcSeedI,
52  label& tgtSeedI
53 ) const
54 {
55  const cellList& srcCells = src_.cells();
56  const faceList& srcFaces = src_.faces();
57  const pointField& srcPts = src_.points();
58 
59  for (label i = startSeedI; i < srcCellIDs.size(); i++)
60  {
61  label srcI = srcCellIDs[i];
62 
63  if (mapFlag[srcI])
64  {
65  const pointField
66  pts(srcCells[srcI].points(srcFaces, srcPts).xfer());
67 
68  forAll(pts, ptI)
69  {
70  const point& pt = pts[ptI];
71  label tgtI = tgt_.cellTree().findInside(pt);
72 
73  if (tgtI != -1 && intersect(srcI, tgtI))
74  {
75  srcSeedI = srcI;
76  tgtSeedI = tgtI;
77 
78  return true;
79  }
80  }
81  }
82  }
83 
84  if (debug)
85  {
86  Pout<< "could not find starting seed" << endl;
87  }
88 
89  return false;
90 }
91 
92 
94 (
95  labelListList& srcToTgtCellAddr,
96  scalarListList& srcToTgtCellWght,
97  labelListList& tgtToSrcCellAddr,
98  scalarListList& tgtToSrcCellWght,
99  const label srcSeedI,
100  const label tgtSeedI,
101  const labelList& srcCellIDs,
102  boolList& mapFlag,
103  label& startSeedI
104 )
105 {
106  label srcCellI = srcSeedI;
107  label tgtCellI = tgtSeedI;
108 
109  List<DynamicList<label> > srcToTgtAddr(src_.nCells());
110  List<DynamicList<scalar> > srcToTgtWght(src_.nCells());
111 
112  List<DynamicList<label> > tgtToSrcAddr(tgt_.nCells());
113  List<DynamicList<scalar> > tgtToSrcWght(tgt_.nCells());
114 
115  // list of tgt cell neighbour cells
116  DynamicList<label> nbrTgtCells(10);
117 
118  // list of tgt cells currently visited for srcCellI to avoid multiple hits
119  DynamicList<label> visitedTgtCells(10);
120 
121  // list to keep track of tgt cells used to seed src cells
122  labelList seedCells(src_.nCells(), -1);
123  seedCells[srcCellI] = tgtCellI;
124 
125  const scalarField& srcVol = src_.cellVolumes();
126 
127  do
128  {
129  nbrTgtCells.clear();
130  visitedTgtCells.clear();
131 
132  // append initial target cell and neighbours
133  nbrTgtCells.append(tgtCellI);
134  appendNbrCells(tgtCellI, tgt_, visitedTgtCells, nbrTgtCells);
135 
136  do
137  {
138  tgtCellI = nbrTgtCells.remove();
139  visitedTgtCells.append(tgtCellI);
140 
141  scalar vol = interVol(srcCellI, tgtCellI);
142 
143  // accumulate addressing and weights for valid intersection
144  if (vol/srcVol[srcCellI] > tolerance_)
145  {
146  // store src/tgt cell pair
147  srcToTgtAddr[srcCellI].append(tgtCellI);
148  srcToTgtWght[srcCellI].append(vol);
149 
150  tgtToSrcAddr[tgtCellI].append(srcCellI);
151  tgtToSrcWght[tgtCellI].append(vol);
152 
153  appendNbrCells(tgtCellI, tgt_, visitedTgtCells, nbrTgtCells);
154 
155  // accumulate intersection volume
156  V_ += vol;
157  }
158  }
159  while (!nbrTgtCells.empty());
160 
161  mapFlag[srcCellI] = false;
162 
163  // find new source seed cell
164  setNextCells
165  (
166  startSeedI,
167  srcCellI,
168  tgtCellI,
169  srcCellIDs,
170  mapFlag,
171  visitedTgtCells,
172  seedCells
173  );
174  }
175  while (srcCellI != -1);
176 
177  // transfer addressing into persistent storage
178  forAll(srcToTgtCellAddr, i)
179  {
180  srcToTgtCellAddr[i].transfer(srcToTgtAddr[i]);
181  srcToTgtCellWght[i].transfer(srcToTgtWght[i]);
182  }
183 
184  forAll(tgtToSrcCellAddr, i)
185  {
186  tgtToSrcCellAddr[i].transfer(tgtToSrcAddr[i]);
187  tgtToSrcCellWght[i].transfer(tgtToSrcWght[i]);
188  }
189 
190 
191  if (debug%2)
192  {
193  // At this point the overlaps are still in volume so we could
194  // get out the relative error
195  forAll(srcToTgtCellAddr, cellI)
196  {
197  scalar srcVol = src_.cellVolumes()[cellI];
198  scalar tgtVol = sum(srcToTgtCellWght[cellI]);
199 
200  if (mag(srcVol) > ROOTVSMALL && mag((tgtVol-srcVol)/srcVol) > 1e-6)
201  {
203  << "At cell " << cellI << " cc:"
204  << src_.cellCentres()[cellI]
205  << " vol:" << srcVol
206  << " total overlap volume:" << tgtVol
207  << endl;
208  }
209  }
210 
211  forAll(tgtToSrcCellAddr, cellI)
212  {
213  scalar tgtVol = tgt_.cellVolumes()[cellI];
214  scalar srcVol = sum(tgtToSrcCellWght[cellI]);
215 
216  if (mag(tgtVol) > ROOTVSMALL && mag((srcVol-tgtVol)/tgtVol) > 1e-6)
217  {
219  << "At cell " << cellI << " cc:"
220  << tgt_.cellCentres()[cellI]
221  << " vol:" << tgtVol
222  << " total overlap volume:" << srcVol
223  << endl;
224  }
225  }
226  }
227 }
228 
229 
231 (
232  label& startSeedI,
233  label& srcCellI,
234  label& tgtCellI,
235  const labelList& srcCellIDs,
236  const boolList& mapFlag,
237  const DynamicList<label>& visitedCells,
238  labelList& seedCells
239 ) const
240 {
241  const labelList& srcNbrCells = src_.cellCells()[srcCellI];
242 
243  // set possible seeds for later use by querying all src cell neighbours
244  // with all visited target cells
245  bool valuesSet = false;
246  forAll(srcNbrCells, i)
247  {
248  label cellS = srcNbrCells[i];
249 
250  if (mapFlag[cellS] && seedCells[cellS] == -1)
251  {
252  forAll(visitedCells, j)
253  {
254  label cellT = visitedCells[j];
255 
256  if (intersect(cellS, cellT))
257  {
258  seedCells[cellS] = cellT;
259 
260  if (!valuesSet)
261  {
262  srcCellI = cellS;
263  tgtCellI = cellT;
264  valuesSet = true;
265  }
266  }
267  }
268  }
269  }
270 
271  // set next src and tgt cells if not set above
272  if (valuesSet)
273  {
274  return;
275  }
276  else
277  {
278  // try to use existing seed
279  bool foundNextSeed = false;
280  for (label i = startSeedI; i < srcCellIDs.size(); i++)
281  {
282  label cellS = srcCellIDs[i];
283 
284  if (mapFlag[cellS])
285  {
286  if (!foundNextSeed)
287  {
288  startSeedI = i;
289  foundNextSeed = true;
290  }
291 
292  if (seedCells[cellS] != -1)
293  {
294  srcCellI = cellS;
295  tgtCellI = seedCells[cellS];
296 
297  return;
298  }
299  }
300  }
301 
302  // perform new search to find match
303  if (debug)
304  {
305  Pout<< "Advancing front stalled: searching for new "
306  << "target cell" << endl;
307  }
308 
309  bool restart =
310  findInitialSeeds
311  (
312  srcCellIDs,
313  mapFlag,
314  startSeedI,
315  srcCellI,
316  tgtCellI
317  );
318 
319  if (restart)
320  {
321  // successfully found new starting seed-pair
322  return;
323  }
324  }
325 
326  // if we have got to here, there are no more src/tgt cell intersections
327  srcCellI = -1;
328  tgtCellI = -1;
329 }
330 
331 
332 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
333 
335 (
336  const polyMesh& src,
337  const polyMesh& tgt
338 )
339 :
340  meshToMeshMethod(src, tgt)
341 {}
342 
343 
344 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
345 
347 {}
348 
349 
350 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
351 
353 (
354  labelListList& srcToTgtAddr,
355  scalarListList& srcToTgtWght,
356  pointListList& srcToTgtVec,
357  labelListList& tgtToSrcAddr,
358  scalarListList& tgtToSrcWght,
359  pointListList& tgtToSrcVec
360 )
361 {
362  bool ok = initialise
363  (
364  srcToTgtAddr,
365  srcToTgtWght,
366  tgtToSrcAddr,
367  tgtToSrcWght
368  );
369 
370  if (!ok)
371  {
372  return;
373  }
374 
375  // (potentially) participating source mesh cells
376  const labelList srcCellIDs(maskCells());
377 
378  // list to keep track of whether src cell can be mapped
379  boolList mapFlag(src_.nCells(), false);
380  UIndirectList<bool>(mapFlag, srcCellIDs) = true;
381 
382  // find initial point in tgt mesh
383  label srcSeedI = -1;
384  label tgtSeedI = -1;
385  label startSeedI = 0;
386 
387  bool startWalk =
388  findInitialSeeds
389  (
390  srcCellIDs,
391  mapFlag,
392  startSeedI,
393  srcSeedI,
394  tgtSeedI
395  );
396 
397  if (startWalk)
398  {
399  calculateAddressing
400  (
401  srcToTgtAddr,
402  srcToTgtWght,
403  tgtToSrcAddr,
404  tgtToSrcWght,
405  srcSeedI,
406  tgtSeedI,
407  srcCellIDs,
408  mapFlag,
409  startSeedI
410  );
411  }
412  else
413  {
414  // if meshes are collocated, after inflating the source mesh bounding
415  // box tgt mesh cells may be transferred, but may still not overlap
416  // with the source mesh
417  return;
418  }
419 }
420 
421 
422 // ************************************************************************* //
Foam::cellVolumeWeightMethod::~cellVolumeWeightMethod
virtual ~cellVolumeWeightMethod()
Destructor.
Definition: cellVolumeWeightMethod.C:346
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::DynamicList< label >
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
indexedOctree.H
Foam::List::transfer
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
Foam::meshToMeshMethod
Base class for mesh-to-mesh calculation methods.
Definition: meshToMeshMethod.H:48
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::List::append
void append(const T &)
Append an element at the end of the list.
Foam::cellVolumeWeightMethod::findInitialSeeds
bool findInitialSeeds(const labelList &srcCellIDs, const boolList &mapFlag, const label startSeedI, label &srcSeedI, label &tgtSeedI) const
Find indices of overlapping cells in src and tgt meshes - returns.
Definition: cellVolumeWeightMethod.C:47
Foam::DynamicList::clear
void clear()
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:242
intersect
Raster intersect(const Raster &rast1, const Raster &rast2)
Definition: Raster.C:666
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
treeDataCell.H
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::cellVolumeWeightMethod::calculate
virtual void calculate(labelListList &srcToTgtAddr, scalarListList &srcToTgtWght, pointListList &srcToTgtVec, labelListList &tgtToSrcAddr, scalarListList &tgtToSrcWght, pointListList &tgtToSrcVec)
Calculate addressing and weights and optionally offset vectors.
Definition: cellVolumeWeightMethod.C:353
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Foam::Vector< scalar >
Foam::cellVolumeWeightMethod::setNextCells
void setNextCells(label &startSeedI, label &srcCellI, label &tgtCellI, const labelList &srcCellIDs, const boolList &mapFlag, const DynamicList< label > &visitedCells, labelList &seedCells) const
Set the next cells in the advancing front algorithm.
Definition: cellVolumeWeightMethod.C:231
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
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: doubleFloat.H:94
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:333
Foam::DynamicList::remove
T remove()
Remove and return the top element.
Definition: DynamicListI.H:365
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:106
cellVolumeWeightMethod.H
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::cellVolumeWeightMethod::calculateAddressing
void calculateAddressing(labelListList &srcToTgtCellAddr, scalarListList &srcToTgtCellWght, labelListList &tgtToSrcCellAddr, scalarListList &tgtToSrcCellWght, const label srcSeedI, const label tgtSeedI, const labelList &srcCellIDs, boolList &mapFlag, label &startSeedI)
Calculate the mesh-to-mesh addressing and weights.
Definition: cellVolumeWeightMethod.C:94
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:259
Foam::cellVolumeWeightMethod::cellVolumeWeightMethod
cellVolumeWeightMethod(const cellVolumeWeightMethod &)
Disallow default bitwise copy construct.