mapNearestAMI.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) 2013-2016 OpenFOAM Foundation
9  Copyright (C) 2016 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 "mapNearestAMI.H"
30 
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 
33 template<class SourcePatch, class TargetPatch>
35 (
36  const SourcePatch& srcPatch,
37  const TargetPatch& tgtPatch,
38  const label& srcFacei,
39  label& tgtFacei
40 ) const
41 {
42  const vectorField& srcCf = srcPatch.faceCentres();
43  const vectorField& tgtCf = tgtPatch.faceCentres();
44 
45  const vector srcP = srcCf[srcFacei];
46 
47  DynamicList<label> tgtFaces(10);
48  tgtFaces.append(tgtFacei);
49 
50  DynamicList<label> visitedFaces(10);
51 
52  scalar d = GREAT;
53 
54  do
55  {
56  label tgtI = tgtFaces.remove();
57  visitedFaces.append(tgtI);
58 
59  scalar dTest = magSqr(tgtCf[tgtI] - srcP);
60  if (dTest < d)
61  {
62  tgtFacei = tgtI;
63  d = dTest;
64 
65  this->appendNbrFaces
66  (
67  tgtFacei,
68  tgtPatch,
69  visitedFaces,
70  tgtFaces
71  );
72  }
73 
74  } while (tgtFaces.size() > 0);
75 }
76 
77 
78 template<class SourcePatch, class TargetPatch>
80 (
81  boolList& mapFlag,
82  label& startSeedI,
83  label& srcFacei,
84  label& tgtFacei
85 ) const
86 {
87  const labelList& srcNbr = this->srcPatch_.faceFaces()[srcFacei];
88 
89  srcFacei = -1;
90 
91  for (const label facei : srcNbr)
92  {
93  if (mapFlag[facei])
94  {
95  srcFacei = facei;
96  startSeedI = facei + 1;
97 
98  return;
99  }
100  }
101 
102  forAll(mapFlag, facei)
103  {
104  if (mapFlag[facei])
105  {
106  srcFacei = facei;
107  tgtFacei = this->findTargetFace(facei);
108 
109  if (tgtFacei == -1)
110  {
111  const vectorField& srcCf = this->srcPatch_.faceCentres();
112 
114  << "Unable to find target face for source face "
115  << srcFacei << " with face centre " << srcCf[srcFacei]
116  << abort(FatalError);
117  }
118 
119  break;
120  }
121  }
122 }
123 
124 
125 template<class SourcePatch, class TargetPatch>
127 (
128  const label tgtFacei,
129  const List<DynamicList<label>>& tgtToSrc
130 ) const
131 {
132  DynamicList<label> testFaces(10);
133  DynamicList<label> visitedFaces(10);
134 
135  testFaces.append(tgtFacei);
136 
137  do
138  {
139  // search target tgtFacei neighbours for match with source face
140  label tgtI = testFaces.remove();
141 
142  if (!visitedFaces.found(tgtI))
143  {
144  visitedFaces.append(tgtI);
145 
146  if (tgtToSrc[tgtI].size())
147  {
148  return tgtToSrc[tgtI][0];
149  }
150  else
151  {
152  const labelList& nbrFaces = this->tgtPatch_.faceFaces()[tgtI];
153 
154  for (const label nbrFacei : nbrFaces)
155  {
156  if (!visitedFaces.found(nbrFacei))
157  {
158  testFaces.append(nbrFacei);
159  }
160  }
161  }
162  }
163  } while (testFaces.size());
164 
165  // did not find any match - should not be possible to get here!
166  return -1;
167 }
168 
169 
170 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
171 
172 template<class SourcePatch, class TargetPatch>
174 (
175  const SourcePatch& srcPatch,
176  const TargetPatch& tgtPatch,
178  const bool reverseTarget,
179  const bool requireMatch
180 )
181 :
183  (
184  srcPatch,
185  tgtPatch,
186  triMode,
187  reverseTarget,
188  requireMatch
189  )
190 {}
191 
192 
193 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
194 
195 template<class SourcePatch, class TargetPatch>
197 {}
198 
199 
200 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
201 
202 template<class SourcePatch, class TargetPatch>
204 (
205  labelListList& srcAddress,
206  scalarListList& srcWeights,
207  labelListList& tgtAddress,
208  scalarListList& tgtWeights,
209  label srcFacei,
210  label tgtFacei
211 )
212 {
213  bool ok =
214  this->initialise
215  (
216  srcAddress,
217  srcWeights,
218  tgtAddress,
219  tgtWeights,
220  srcFacei,
221  tgtFacei
222  );
223 
224  if (!ok)
225  {
226  return;
227  }
228 
229 
230  // temporary storage for addressing and weights
231  List<DynamicList<label>> srcAddr(this->srcPatch_.size());
232  List<DynamicList<label>> tgtAddr(this->tgtPatch_.size());
233 
234 
235  // construct weights and addressing
236  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
237 
238  // list to keep track of whether src face can be mapped
239  boolList mapFlag(srcAddr.size(), true);
240 
241  // reset starting seed
242  label startSeedI = 0;
243 
244  DynamicList<label> nonOverlapFaces;
245  do
246  {
247  findNearestFace(this->srcPatch_, this->tgtPatch_, srcFacei, tgtFacei);
248 
249  srcAddr[srcFacei].append(tgtFacei);
250  tgtAddr[tgtFacei].append(srcFacei);
251 
252  mapFlag[srcFacei] = false;
253 
254  // Do advancing front starting from srcFacei, tgtFacei
255  setNextNearestFaces
256  (
257  mapFlag,
258  startSeedI,
259  srcFacei,
260  tgtFacei
261  );
262  } while (srcFacei >= 0);
263 
264 
265  // for the case of multiple source faces per target face, select the
266  // nearest source face only and discard the others
267  const vectorField& srcCf = this->srcPatch_.faceCentres();
268  const vectorField& tgtCf = this->tgtPatch_.faceCentres();
269 
270  forAll(tgtAddr, targetFacei)
271  {
272  if (tgtAddr[targetFacei].size() > 1)
273  {
274  const vector& tgtC = tgtCf[tgtFacei];
275 
276  DynamicList<label>& srcFaces = tgtAddr[targetFacei];
277 
278  label srcFacei = srcFaces[0];
279  scalar d = magSqr(tgtC - srcCf[srcFacei]);
280 
281  for (label i = 1; i < srcFaces.size(); ++i)
282  {
283  label srcI = srcFaces[i];
284  scalar dNew = magSqr(tgtC - srcCf[srcI]);
285  if (dNew < d)
286  {
287  d = dNew;
288  srcFacei = srcI;
289  }
290  }
291 
292  srcFaces.clear();
293  srcFaces.append(srcFacei);
294  }
295  }
296 
297  // If there are more target faces than source faces, some target faces
298  // might not yet be mapped
299  forAll(tgtAddr, tgtFacei)
300  {
301  if (tgtAddr[tgtFacei].empty())
302  {
303  label srcFacei = findMappedSrcFace(tgtFacei, tgtAddr);
304 
305  if (srcFacei >= 0)
306  {
307  // note - reversed search from src->tgt to tgt->src
308  findNearestFace
309  (
310  this->tgtPatch_,
311  this->srcPatch_,
312  tgtFacei,
313  srcFacei
314  );
315 
316  tgtAddr[tgtFacei].append(srcFacei);
317  }
318  }
319  }
320 
321 
322  // transfer data to persistent storage
323  const pointField& srcFc = this->srcPatch_.faceCentres();
324  const pointField& tgtFc = this->tgtPatch_.faceCentres();
325 
326  forAll(srcAddr, srcI)
327  {
328  srcAddress[srcI].transfer(srcAddr[srcI]);
329 
330  const labelList& addr = srcAddress[srcI];
331  srcWeights[srcI].setSize(addr.size());
332  const point& srcPt = srcFc[srcI];
333  forAll(addr, i)
334  {
335  srcWeights[srcI][i] = magSqr(srcPt-tgtFc[addr[i]]);
336  }
337  }
338  forAll(tgtAddr, tgtI)
339  {
340  tgtAddress[tgtI].transfer(tgtAddr[tgtI]);
341 
342  const labelList& addr = tgtAddress[tgtI];
343  tgtWeights[tgtI].setSize(addr.size());
344  const point& tgtPt = tgtFc[tgtI];
345  forAll(addr, i)
346  {
347  tgtWeights[tgtI][i] = magSqr(tgtPt-srcFc[addr[i]]);
348  }
349  }
350 }
351 
352 
353 template<class SourcePatch, class TargetPatch>
355 (
356  const TargetPatch& tgtPatch,
357  const mapDistribute& map,
358  scalarList& srcMagSf,
359  scalarList& tgtMagSf
360 ) const
361 {
362  srcMagSf = std::move(this->srcMagSf_);
363  tgtMagSf = scalarList(tgtPatch.size(), 1.0);
364 }
365 
366 
367 template<class SourcePatch, class TargetPatch>
369 (
370  const bool verbose,
372 )
373 {
374  {
375  labelListList& srcAddress = inter.srcAddress();
376  scalarListList& srcWeights = inter.srcWeights();
377 
378  forAll(srcAddress, srcI)
379  {
380  labelList& addr = srcAddress[srcI];
381  scalarList& wghts = srcWeights[srcI];
382 
383  // Choose one with smallest weight (since calculate above returns
384  // distance)
385  if (addr.size())
386  {
387  label minFaceI = addr[0];
388  scalar minWeight = wghts[0];
389 
390  for (label i = 0; i < addr.size(); ++i)
391  {
392  if (wghts[i] < minWeight)
393  {
394  minWeight = wghts[i];
395  minFaceI = addr[i];
396  }
397  }
398 
399  wghts.setSize(1);
400  wghts[0] = this->srcMagSf_[srcI];
401  addr.setSize(1);
402  addr[0] = minFaceI;
403  }
404  }
405  }
406 
407  {
408  labelListList& tgtAddress = inter.tgtAddress();
409  scalarListList& tgtWeights = inter.tgtWeights();
410 
411  forAll(tgtAddress, tgtI)
412  {
413  labelList& addr = tgtAddress[tgtI];
414  scalarList& wghts = tgtWeights[tgtI];
415 
416  // Choose one with smallest weight (since calculate above returns
417  // distance)
418  if (addr.size())
419  {
420  label minFaceI = addr[0];
421  scalar minWeight = wghts[0];
422 
423  forAll(addr, i)
424  {
425  if (wghts[i] < minWeight)
426  {
427  minWeight = wghts[i];
428  minFaceI = addr[i];
429  }
430  }
431 
432  wghts.setSize(1);
433  wghts[0] = inter.tgtMagSf()[tgtI];
434  addr.setSize(1);
435  addr[0] = minFaceI;
436  }
437  }
438  }
439 
440  inter.normaliseWeights(this->conformal(), verbose);
441 }
442 
443 
444 // ************************************************************************* //
Foam::mapNearestAMI::calculate
virtual void calculate(labelListList &srcAddress, scalarListList &srcWeights, labelListList &tgtAddress, scalarListList &tgtWeights, label srcFacei=-1, label tgtFacei=-1)
Update addressing and weights.
Definition: mapNearestAMI.C:204
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
Foam::scalarList
List< scalar > scalarList
A List of scalars.
Definition: scalarList.H:64
Foam::faceAreaIntersect::triangulationMode
triangulationMode
Definition: faceAreaIntersect.H:62
Foam::DynamicList< label >
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:72
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:182
Foam::mapNearestAMI
Nearest-mapping Arbitrary Mesh Interface (AMI) method.
Definition: mapNearestAMI.H:52
Foam::AMIInterpolation::tgtAddress
const labelListList & tgtAddress() const
Return const access to target patch addressing.
Definition: AMIInterpolationI.H:144
Foam::AMIInterpolation::tgtWeights
const scalarListList & tgtWeights() const
Return const access to target patch weights.
Definition: AMIInterpolationI.H:160
Foam::AMIMethod
Base class for Arbitrary Mesh Interface (AMI) methods.
Definition: AMIMethod.H:60
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:54
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Foam::mapNearestAMI::normaliseWeights
virtual void normaliseWeights(const bool verbose, AMIInterpolation< SourcePatch, TargetPatch > &inter)
Definition: mapNearestAMI.C:369
Foam::mapNearestAMI::~mapNearestAMI
virtual ~mapNearestAMI()
Destructor.
Definition: mapNearestAMI.C:196
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:62
Foam::Field< vector >
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:472
Foam::mapDistribute
Class containing processor-to-processor mapping information.
Definition: mapDistribute.H:163
Foam::DynamicList::clear
void clear()
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:348
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:436
Foam::FatalError
error FatalError
Foam::mapNearestAMI::setMagSf
virtual void setMagSf(const TargetPatch &tgtPatch, const mapDistribute &map, scalarList &srcMagSf, scalarList &tgtMagSf) const
Set the face areas for parallel runs.
Definition: mapNearestAMI.C:355
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::Vector< scalar >
Foam::List< labelList >
Foam::AMIInterpolation
Interpolation class dealing with transfer of data between two primitive patches with an arbitrary mes...
Definition: AMIInterpolation.H:81
mapNearestAMI.H
Foam::AMIInterpolation::tgtMagSf
const List< scalar > & tgtMagSf() const
Return const access to target patch face areas.
Definition: AMIInterpolationI.H:128
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::AMIInterpolation::srcAddress
const labelListList & srcAddress() const
Return const access to source patch addressing.
Definition: AMIInterpolationI.H:72
Foam::AMIInterpolation::srcWeights
const scalarListList & srcWeights() const
Return const access to source patch weights.
Definition: AMIInterpolationI.H:88