fvMeshSubsetInterpolate.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) 2019-2020 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 "fvMeshSubset.H"
30 #include "emptyFvsPatchField.H"
31 #include "emptyPointPatchField.H"
32 #include "emptyFvPatchFields.H"
35 #include "flipOp.H"
36 
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 
39 template<class Type>
41 <
43 >
45 (
46  const GeometricField<Type, fvPatchField, volMesh>& vf,
47  const fvMesh& sMesh,
48  const labelUList& patchMap,
49  const labelUList& cellMap,
50  const labelUList& faceMap,
51  const bool allowUnmapped
52 )
53 {
54  // 1. Create the complete field with dummy patch fields
55  PtrList<fvPatchField<Type>> patchFields(patchMap.size());
56 
57  forAll(patchFields, patchi)
58  {
59  // Set the first one by hand as it corresponds to the
60  // exposed internal faces. Additional interpolation can be put here
61  // as necessary.
62  if (patchMap[patchi] == -1)
63  {
64  patchFields.set
65  (
66  patchi,
67  new emptyFvPatchField<Type>
68  (
69  sMesh.boundary()[patchi],
71  )
72  );
73  }
74  else
75  {
76  patchFields.set
77  (
78  patchi,
80  (
81  calculatedFvPatchField<Type>::typeName,
82  sMesh.boundary()[patchi],
84  )
85  );
86  }
87  }
88 
89  auto tresult = tmp<GeometricField<Type, fvPatchField, volMesh>>::New
90  (
91  IOobject
92  (
93  "subset"+vf.name(),
94  sMesh.time().timeName(),
95  sMesh,
98  ),
99  sMesh,
100  vf.dimensions(),
101  Field<Type>(vf.primitiveField(), cellMap),
102  patchFields
103  );
104  auto& result = tresult.ref();
105  result.oriented() = vf.oriented();
106 
107 
108  // 2. Change the fvPatchFields to the correct type using a mapper
109  // constructor (with reference to the now correct internal field)
110 
111  auto& bf = result.boundaryFieldRef();
112 
113  forAll(bf, patchi)
114  {
115  const label basePatchId = patchMap[patchi];
116 
117  if (basePatchId != -1)
118  {
119  // Construct addressing
120  const fvPatch& subPatch = sMesh.boundary()[patchi];
121  const fvPatch& basePatch = vf.mesh().boundary()[basePatchId];
122  const label baseStart = basePatch.start();
123  const label baseSize = basePatch.size();
124 
125  labelList directAddressing(subPatch.size());
126 
127  forAll(directAddressing, i)
128  {
129  const label baseFacei = faceMap[subPatch.start()+i];
130 
131  if (baseFacei >= baseStart && baseFacei < baseStart+baseSize)
132  {
133  directAddressing[i] = baseFacei-baseStart;
134  }
135  else
136  {
137  // Mapped from internal face. Do what? Leave up to
138  // fvPatchField
139  directAddressing[i] = -1;
140  }
141  }
142 
143 
144  directFvPatchFieldMapper mapper(directAddressing);
145 
146  // allowUnmapped : special mode for if we do not want to be
147  // warned for unmapped faces (e.g. from fvMeshDistribute).
148  const bool hasUnmapped = mapper.hasUnmapped();
149  if (allowUnmapped)
150  {
151  mapper.hasUnmapped() = false;
152  }
153 
154  bf.set
155  (
156  patchi,
158  (
159  vf.boundaryField()[basePatchId],
160  subPatch,
161  result(),
162  mapper
163  )
164  );
165 
166  if (allowUnmapped && hasUnmapped)
167  {
168  // Set unmapped values to zeroGradient. This is the default
169  // action for unmapped fvPatchFields. Note that this bypasses
170  // any special logic for handling unmapped fvPatchFields but
171  // since this is only used inside fvMeshDistribute ...
172 
173  tmp<Field<Type>> tfld(bf[patchi].patchInternalField());
174  const Field<Type>& fld = tfld();
175 
176  Field<Type> value(bf[patchi]);
177  forAll(directAddressing, i)
178  {
179  if (directAddressing[i] == -1)
180  {
181  value[i] = fld[i];
182  }
183  }
184  bf[patchi].fvPatchField<Type>::operator=(value);
185  }
186  }
187  }
188 
189  return tresult;
190 }
191 
192 
193 template<class Type>
194 Foam::tmp
195 <
197 >
199 (
200  const GeometricField<Type, fvPatchField, volMesh>& vf,
201  const bool allowUnmapped
202 ) const
203 {
204  return interpolate
205  (
206  vf,
207  subMesh(),
208  patchMap(),
209  cellMap(),
210  faceMap(),
211  allowUnmapped
212  );
213 }
214 
215 
216 template<class Type>
217 Foam::tmp
218 <
220 >
222 (
223  const GeometricField<Type, fvsPatchField, surfaceMesh>& vf,
224  const fvMesh& sMesh,
225  const labelUList& patchMap,
226  const labelUList& cellMap,
227  const labelUList& faceMap
228 )
229 {
230  // 1. Create the complete field with dummy patch fields
231  PtrList<fvsPatchField<Type>> patchFields(patchMap.size());
232 
233  forAll(patchFields, patchi)
234  {
235  // Set the first one by hand as it corresponds to the
236  // exposed internal faces. Additional interpolation can be put here
237  // as necessary.
238  if (patchMap[patchi] == -1)
239  {
240  patchFields.set
241  (
242  patchi,
243  new emptyFvsPatchField<Type>
244  (
245  sMesh.boundary()[patchi],
247  )
248  );
249  }
250  else
251  {
252  patchFields.set
253  (
254  patchi,
256  (
257  calculatedFvsPatchField<Type>::typeName,
258  sMesh.boundary()[patchi],
260  )
261  );
262  }
263  }
264 
265  // Create the complete field from the pieces
266  auto tresult = tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>::New
267  (
268  IOobject
269  (
270  "subset"+vf.name(),
271  sMesh.time().timeName(),
272  sMesh,
275  ),
276  sMesh,
277  vf.dimensions(),
278  Field<Type>
279  (
280  vf.primitiveField(),
281  SubList<label>(faceMap, sMesh.nInternalFaces())
282  ),
283  patchFields
284  );
285  auto& result = tresult.ref();
286  result.oriented() = vf.oriented();
287 
288 
289  // 2. Change the fvsPatchFields to the correct type using a mapper
290  // constructor (with reference to the now correct internal field)
291 
292  auto& bf = result.boundaryFieldRef();
293 
294  forAll(bf, patchi)
295  {
296  if (patchMap[patchi] != -1)
297  {
298  // Construct addressing
299  const fvPatch& subPatch = sMesh.boundary()[patchi];
300  const fvPatch& basePatch = vf.mesh().boundary()[patchMap[patchi]];
301  const label baseStart = basePatch.start();
302  const label baseSize = basePatch.size();
303 
304  labelList directAddressing(subPatch.size());
305 
306  forAll(directAddressing, i)
307  {
308  label baseFacei = faceMap[subPatch.start()+i];
309 
310  if (baseFacei >= baseStart && baseFacei < baseStart+baseSize)
311  {
312  directAddressing[i] = baseFacei-baseStart;
313  }
314  else
315  {
316  // Mapped from internal face. Do what? Leave up to
317  // patchField. This would require also to pass in
318  // original internal field so for now do as post-processing
319  directAddressing[i] = -1;
320  }
321  }
322 
323  bf.set
324  (
325  patchi,
327  (
328  vf.boundaryField()[patchMap[patchi]],
329  subPatch,
330  result(),
331  directFvPatchFieldMapper(directAddressing)
332  )
333  );
334 
335 
336  // Post-process patch field for exposed faces
337 
338  fvsPatchField<Type>& pfld = bf[patchi];
339  const labelUList& fc = bf[patchi].patch().faceCells();
340  const labelList& own = vf.mesh().faceOwner();
341 
342  forAll(pfld, i)
343  {
344  label baseFacei = faceMap[subPatch.start()+i];
345  if (baseFacei < vf.primitiveField().size())
346  {
347  Type val = vf.internalField()[baseFacei];
348 
349  if (cellMap[fc[i]] == own[baseFacei] || !vf.oriented()())
350  {
351  pfld[i] = val;
352  }
353  else
354  {
355  pfld[i] = flipOp()(val);
356  }
357  }
358  else
359  {
360  // Exposed face from other patch.
361  // Only possible in case of a coupled boundary
362  label patchi = vf.mesh().boundaryMesh().whichPatch
363  (
364  baseFacei
365  );
366  const fvPatch& otherPatch = vf.mesh().boundary()[patchi];
367  label patchFacei = otherPatch.patch().whichFace(baseFacei);
368  pfld[i] = vf.boundaryField()[patchi][patchFacei];
369  }
370  }
371  }
372  }
373 
374  return tresult;
375 }
376 
377 
378 template<class Type>
379 Foam::tmp
380 <
382 >
384 (
385  const GeometricField<Type, fvsPatchField, surfaceMesh>& sf,
386  const bool allowUnmapped
387 ) const
388 {
389  return interpolate
390  (
391  sf,
392  subMesh(),
393  patchMap(),
394  cellMap(),
395  faceMap()
396  );
397 }
398 
399 
400 template<class Type>
401 Foam::tmp
402 <
404 >
406 (
407  const GeometricField<Type, pointPatchField, pointMesh>& vf,
408  const pointMesh& sMesh,
409  const labelUList& patchMap,
410  const labelUList& pointMap
411 )
412 {
413  // 1. Create the complete field with dummy patch fields
414  PtrList<pointPatchField<Type>> patchFields(patchMap.size());
415 
416  forAll(patchFields, patchi)
417  {
418  // Set the first one by hand as it corresponds to the
419  // exposed internal faces. Additional interpolation can be put here
420  // as necessary.
421  if (patchMap[patchi] == -1)
422  {
423  patchFields.set
424  (
425  patchi,
426  new emptyPointPatchField<Type>
427  (
428  sMesh.boundary()[patchi],
430  )
431  );
432  }
433  else
434  {
435  patchFields.set
436  (
437  patchi,
439  (
440  calculatedPointPatchField<Type>::typeName,
441  sMesh.boundary()[patchi],
443  )
444  );
445  }
446  }
447 
448  // Create the complete field from the pieces
449  auto tresult = tmp<GeometricField<Type, pointPatchField, pointMesh>>::New
450  (
451  IOobject
452  (
453  "subset"+vf.name(),
454  sMesh.time().timeName(),
455  sMesh.thisDb(),
458  ),
459  sMesh,
460  vf.dimensions(),
461  Field<Type>(vf.primitiveField(), pointMap),
462  patchFields
463  );
464  auto& result = tresult.ref();
465  result.oriented() = vf.oriented();
466 
467 
468  // 2. Change the pointPatchFields to the correct type using a mapper
469  // constructor (with reference to the now correct internal field)
470 
471  auto& bf = result.boundaryFieldRef();
472 
473  forAll(bf, patchi)
474  {
475  // Set the first one by hand as it corresponds to the
476  // exposed internal faces. Additional interpolation can be put here
477  // as necessary.
478  if (patchMap[patchi] != -1)
479  {
480  // Construct addressing
481  const pointPatch& basePatch =
482  vf.mesh().boundary()[patchMap[patchi]];
483 
484  const labelList& meshPoints = basePatch.meshPoints();
485 
486  // Make addressing from mesh to patch point
487  Map<label> meshPointMap(2*meshPoints.size());
488  forAll(meshPoints, localI)
489  {
490  meshPointMap.insert(meshPoints[localI], localI);
491  }
492 
493  // Find which subpatch points originate from which patch point
494  const pointPatch& subPatch = sMesh.boundary()[patchi];
495  const labelList& subMeshPoints = subPatch.meshPoints();
496 
497  // If mapped from outside patch leave handling up to patchField
498  labelList directAddressing(subPatch.size(), -1);
499 
500  forAll(subMeshPoints, localI)
501  {
502  // Get mesh point on original mesh.
503  label meshPointi = pointMap[subMeshPoints[localI]];
504 
505  const auto iter = meshPointMap.cfind(meshPointi);
506 
507  if (iter.found())
508  {
509  directAddressing[localI] = *iter;
510  }
511  }
512 
513  bf.set
514  (
515  patchi,
517  (
518  vf.boundaryField()[patchMap[patchi]],
519  subPatch,
520  result(),
521  directPointPatchFieldMapper(directAddressing)
522  )
523  );
524  }
525  }
526 
527  return tresult;
528 }
529 
530 
531 template<class Type>
532 Foam::tmp
533 <
535 >
537 (
538  const GeometricField<Type, pointPatchField, pointMesh>& sf,
539  const bool allowUnmapped
540 ) const
541 {
542  return interpolate
543  (
544  sf,
545  pointMesh::New(subMesh()), // subsetted point mesh
546  patchMap(),
547  pointMap()
548  );
549 }
550 
551 
552 template<class Type>
553 Foam::tmp
554 <
556 >
558 (
559  const DimensionedField<Type, volMesh>& df,
560  const fvMesh& sMesh,
561  const labelUList& cellMap
562 )
563 {
564  auto tresult = tmp<DimensionedField<Type, volMesh>>::New
565  (
566  IOobject
567  (
568  "subset"+df.name(),
569  sMesh.time().timeName(),
570  sMesh,
573  ),
574  sMesh,
575  df.dimensions(),
576  Field<Type>(df, cellMap)
577  );
578  tresult.ref().oriented() = df.oriented();
579 
580  return tresult;
581 }
582 
583 
584 template<class Type>
585 Foam::tmp
586 <
588 >
590 (
591  const DimensionedField<Type, volMesh>& df,
592  const bool allowUnmapped
593 ) const
594 {
595  return interpolate(df, subMesh(), cellMap());
596 }
597 
598 
599 // ************************************************************************* //
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
emptyPointPatchField.H
directPointPatchFieldMapper.H
Foam::fvMeshSubset::cellMap
const labelList & cellMap() const
Return cell map.
Definition: fvMeshSubsetI.H:91
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
fvMeshSubset.H
Foam::MeshObject< polyMesh, UpdateableMeshObject, pointMesh >::New
static const pointMesh & New(const polyMesh &mesh, Args &&... args)
Get existing or create a new MeshObject.
Definition: MeshObject.C:48
Foam::DimensionedField::null
static const DimensionedField< Type, GeoMesh > & null()
Return a NullObjectRef DimensionedField.
Definition: DimensionedFieldI.H:33
emptyFvsPatchField.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::interpolate
bool interpolate(const vector &p1, const vector &p2, const vector &o, vector &n, scalar l)
Definition: curveTools.C:75
directFvPatchFieldMapper.H
emptyFvPatchFields.H
fld
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputLagrangian.H:23
Foam::fvsPatchField::New
static tmp< fvsPatchField< Type > > New(const word &, const fvPatch &, const DimensionedField< Type, surfaceMesh > &)
Return a pointer to a new patchField created on freestore given.
Definition: fvsPatchFieldNew.C:74
Foam::pointPatchField::New
static autoPtr< pointPatchField< Type > > New(const word &, const pointPatch &, const DimensionedField< Type, pointMesh > &)
Return a pointer to a new patchField created on freestore given.
Definition: pointPatchFieldNew.C:95
flipOp.H
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
Foam::fvPatchField::New
static tmp< fvPatchField< Type > > New(const word &, const fvPatch &, const DimensionedField< Type, volMesh > &)
Return a pointer to a new patchField created on freestore given.
Definition: fvPatchFieldNew.C:88
Foam::fvMeshSubset::interpolate
static tmp< GeometricField< Type, fvPatchField, volMesh > > interpolate(const GeometricField< Type, fvPatchField, volMesh > &, const fvMesh &sMesh, const labelUList &patchMap, const labelUList &cellMap, const labelUList &faceMap, const bool allowUnmapped=false)
Map volume field. Optionally allow unmapped faces not to produce.
Foam::fvMeshSubset::faceMap
const labelList & faceMap() const
Return face map.
Definition: fvMeshSubsetI.H:72
Foam::fvMeshSubset::patchMap
const labelList & patchMap() const
Return patch map.
Definition: fvMeshSubsetI.H:99
Foam::labelUList
UList< label > labelUList
A UList of labels.
Definition: UList.H:85
Foam::GeometricField< Type, Foam::fvPatchField, Foam::volMesh >
Foam::IOobject::NO_READ
Definition: IOobject.H:188
Foam::DimensionedField< Type, Foam::volMesh >