fvMeshSubsetInterpolate.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 OpenFOAM Foundation
6  \\/ M anipulation |
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 "fvMeshSubset.H"
27 #include "surfaceFields.H"
28 #include "internalFvsPatchField.H"
30 #include "internalFvPatchFields.H"
31 #include "forwardFieldMapper.H"
32 #include "flipOp.H"
33 
34 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
35 
36 template<class Type>
39 (
40  const VolField<Type>& vf,
41  const fvMesh& sMesh,
42  const labelList& patchMap,
43  const labelList& cellMap,
44  const labelList& faceMap
45 )
46 {
47  // 1. Create the complete field with dummy patch fields
49 
50  forAll(patchFields, patchi)
51  {
52  // Set the first one by hand as it corresponds to the
53  // exposed internal faces. Additional interpolation can be put here
54  // as necessary.
55  if (patchMap[patchi] == -1)
56  {
57  patchFields.set
58  (
59  patchi,
61  (
62  sMesh.boundary()[patchi],
64  )
65  );
66  }
67  else
68  {
69  patchFields.set
70  (
71  patchi,
73  (
75  sMesh.boundary()[patchi],
77  )
78  );
79  }
80  }
81 
82  tmp<VolField<Type>> tresF
83  (
84  new VolField<Type>
85  (
86  IOobject
87  (
88  "subset"+vf.name(),
89  sMesh.time().name(),
90  sMesh,
93  false
94  ),
95  sMesh,
96  vf.dimensions(),
98  patchFields
99  )
100  );
101  VolField<Type>& resF = tresF.ref();
102 
103 
104  // 2. Change the fvPatchFields to the correct type using a mapper
105  // constructor (with reference to the now correct internal field)
106 
107  typename VolField<Type>::
108  Boundary& bf = resF.boundaryFieldRef();
109 
110  forAll(bf, patchi)
111  {
112  if (patchMap[patchi] != -1)
113  {
114  // Construct addressing
115  const fvPatch& subPatch = sMesh.boundary()[patchi];
116  const fvPatch& basePatch = vf.mesh().boundary()[patchMap[patchi]];
117  const label baseStart = basePatch.start();
118  const label baseSize = basePatch.size();
119 
120  labelList directAddressing(subPatch.size());
121 
122  forAll(directAddressing, i)
123  {
124  const label baseFacei = faceMap[subPatch.start() + i];
125 
126  if (baseFacei >= baseStart && baseFacei < baseStart+baseSize)
127  {
128  directAddressing[i] = baseFacei-baseStart;
129  }
130  else
131  {
132  // Mapped from internal face. Do what? Leave up to
133  // fvPatchField
134  directAddressing[i] = -1;
135  }
136  }
137 
138  bf.set
139  (
140  patchi,
142  (
144  subPatch,
145  resF(),
146  forwardFieldMapper(directAddressing)
147  )
148  );
149  }
150  }
151 
152  return tresF;
153 }
154 
155 
156 template<class Type>
159 (
160  const VolField<Type>& vf
161 ) const
162 {
163  return interpolate
164  (
165  vf,
166  subMesh(),
167  patchMap(),
168  cellMap(),
169  faceMap()
170  );
171 }
172 
173 
174 template<class Type>
177 (
178  const SurfaceField<Type>& sf,
179  const fvMesh& sMesh,
180  const labelList& patchMap,
181  const labelList& cellMap,
182  const labelList& faceMap
183 )
184 {
185  const bool negateIfFlipped = isFlux(sf);
186 
187  // 1. Create the complete field with dummy patch fields
188  PtrList<fvsPatchField<Type>> patchFields(patchMap.size());
189 
190  forAll(patchFields, patchi)
191  {
192  // Set the first one by hand as it corresponds to the
193  // exposed internal faces. Additional interpolation can be put here
194  // as necessary.
195  if (patchMap[patchi] == -1)
196  {
197  patchFields.set
198  (
199  patchi,
201  (
202  sMesh.boundary()[patchi],
204  )
205  );
206  }
207  else
208  {
209  patchFields.set
210  (
211  patchi,
213  (
215  sMesh.boundary()[patchi],
217  )
218  );
219  }
220  }
221 
222  // Create the complete field from the pieces
224  (
226  (
227  IOobject
228  (
229  "subset"+sf.name(),
230  sMesh.time().name(),
231  sMesh,
234  false
235  ),
236  sMesh,
237  sf.dimensions(),
239  (
240  sf.primitiveField(),
242  (
243  faceMap,
244  sMesh.nInternalFaces()
245  )
246  ),
247  patchFields
248  )
249  );
250  SurfaceField<Type>& resF = tresF.ref();
251 
252  // 2. Change the fvsPatchFields to the correct type using a mapper
253  // constructor (with reference to the now correct internal field)
254 
255  typename SurfaceField<Type>::
256  Boundary& bf = resF.boundaryFieldRef();
257 
258  forAll(bf, patchi)
259  {
260  const fvPatch& subPatch = sMesh.boundary()[patchi];
261 
262  labelList directAddressing(subPatch.size(), -1);
263 
264  if (patchMap[patchi] != -1)
265  {
266  // Construct addressing
267  const fvPatch& basePatch = sf.mesh().boundary()[patchMap[patchi]];
268  const label baseStart = basePatch.start();
269  const label baseSize = basePatch.size();
270 
271  forAll(directAddressing, i)
272  {
273  const label baseFacei = faceMap[subPatch.start() + i];
274 
275  if (baseFacei >= baseStart && baseFacei < baseStart+baseSize)
276  {
277  directAddressing[i] = baseFacei-baseStart;
278  }
279  }
280 
281  bf.set
282  (
283  patchi,
285  (
286  sf.boundaryField()[patchMap[patchi]],
287  subPatch,
288  resF(),
289  forwardFieldMapper(directAddressing)
290  )
291  );
292  }
293 
294  // Map internal face values onto the patch elected to hold
295  // the exposed faces
296  const polyMesh& mesh = sf.mesh()();
297  fvsPatchField<Type>& pfld = bf[patchi];
298  const labelUList& fc = bf[patchi].patch().faceCells();
299  const labelList& own = mesh.faceOwner();
300 
301  forAll(pfld, i)
302  {
303  const label baseFacei = faceMap[subPatch.start() + i];
304 
305  if (directAddressing[i] == -1)
306  {
307  if (mesh.isInternalFace(baseFacei))
308  {
309  const Type val = sf.internalField()[baseFacei];
310 
311  if (cellMap[fc[i]] == own[baseFacei] || !negateIfFlipped)
312  {
313  pfld[i] = val;
314  }
315  else
316  {
317  pfld[i] = flipOp()(val);
318  }
319  }
320  else
321  {
322  const label basePatchi =
323  mesh.boundary().patchIndices()
324  [baseFacei - mesh.nInternalFaces()];
325  const label basePatchFacei =
326  mesh.boundary()[basePatchi]
327  .whichFace(baseFacei);
328 
329  pfld[i] = sf.boundaryField()[basePatchi][basePatchFacei];
330  }
331  }
332  }
333  }
334 
335  return tresF;
336 }
337 
338 
339 template<class Type>
342 (
343  const SurfaceField<Type>& sf
344 ) const
345 {
346  return interpolate
347  (
348  sf,
349  subMesh(),
350  patchMap(),
351  cellMap(),
352  faceMap()
353  );
354 }
355 
356 
357 template<class Type>
360 (
361  const PointField<Type>& pf,
362  const pointMesh& sMesh,
363  const labelList& patchMap,
364  const labelList& pointMap
365 )
366 {
367  // 1. Create the complete field with dummy patch fields
368  PtrList<pointPatchField<Type>> patchFields(patchMap.size());
369 
370  forAll(patchFields, patchi)
371  {
372  // Set the first one by hand as it corresponds to the
373  // exposed internal faces. Additional interpolation can be put here
374  // as necessary.
375  if (patchMap[patchi] == -1)
376  {
377  patchFields.set
378  (
379  patchi,
381  (
382  sMesh.boundary()[patchi],
384  )
385  );
386  }
387  else
388  {
389  patchFields.set
390  (
391  patchi,
393  (
395  sMesh.boundary()[patchi],
397  )
398  );
399  }
400  }
401 
402  // Create the complete field from the pieces
403  tmp<PointField<Type>> tresF
404  (
405  new PointField<Type>
406  (
407  IOobject
408  (
409  "subset"+pf.name(),
410  sMesh.time().name(),
411  sMesh.db(),
414  false
415  ),
416  sMesh,
417  pf.dimensions(),
418  Field<Type>(pf.primitiveField(), pointMap),
419  patchFields
420  )
421  );
422  PointField<Type>& resF = tresF.ref();
423 
424 
425  // 2. Change the pointPatchFields to the correct type using a mapper
426  // constructor (with reference to the now correct internal field)
427 
428  typename PointField<Type>::
429  Boundary& bf = resF.boundaryFieldRef();
430 
431  forAll(bf, patchi)
432  {
433  // Set the first one by hand as it corresponds to the
434  // exposed internal faces. Additional interpolation can be put here
435  // as necessary.
436  if (patchMap[patchi] != -1)
437  {
438  // Construct addressing
439  const pointPatch& basePatch =
440  pf.mesh().boundary()[patchMap[patchi]];
441 
442  const labelList& meshPoints = basePatch.meshPoints();
443 
444  // Make addressing from mesh to patch point
445  Map<label> meshPointMap(2*meshPoints.size());
446  forAll(meshPoints, localI)
447  {
448  meshPointMap.insert(meshPoints[localI], localI);
449  }
450 
451  // Find which subpatch points originate from which patch point
452  const pointPatch& subPatch = sMesh.boundary()[patchi];
453  const labelList& subMeshPoints = subPatch.meshPoints();
454 
455  // If mapped from outside patch leave handling up to patchField
456  labelList directAddressing(subPatch.size(), -1);
457 
458  forAll(subMeshPoints, localI)
459  {
460  // Get mesh point on original mesh.
461  label meshPointi = pointMap[subMeshPoints[localI]];
462 
463  Map<label>::const_iterator iter = meshPointMap.find(meshPointi);
464 
465  if (iter != meshPointMap.end())
466  {
467  directAddressing[localI] = iter();
468  }
469  }
470 
471  bf.set
472  (
473  patchi,
475  (
476  pf.boundaryField()[patchMap[patchi]],
477  subPatch,
478  resF(),
479  forwardFieldMapper(directAddressing)
480  )
481  );
482  }
483  }
484 
485  return tresF;
486 }
487 
488 
489 template<class Type>
492 (
493  const PointField<Type>& sf
494 ) const
495 {
496  return interpolate
497  (
498  sf,
499  pointMesh::New(subMesh()), // subsetted point mesh
500  patchMap(),
501  pointMap()
502  );
503 }
504 
505 
506 template<class Type>
509 (
511  const fvMesh& sMesh,
512  const labelList& cellMap
513 )
514 {
515  // Create the complete field from the pieces
517  (
519  (
520  IOobject
521  (
522  "subset"+df.name(),
523  sMesh.time().name(),
524  sMesh,
527  ),
528  sMesh,
529  df.dimensions(),
530  Field<Type>(df, cellMap)
531  )
532  );
533 
534  return tresF;
535 }
536 
537 
538 template<class Type>
541 (
543 ) const
544 {
545  return interpolate(df, subMesh(), cellMap());
546 }
547 
548 
549 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
static pointMesh & New(const word &name, const polyMesh &mesh)
Construct and return the named DemandDrivenMeshObject.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
const dimensionSet & dimensions() const
Return dimensions.
const GeoMesh & mesh() const
Return mesh.
Pre-declare SubField and related Field type.
Definition: Field.H:83
Generic GeometricField class.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
const Internal & internalField() const
Return a const-reference to the dimensioned internal field.
Boundary & boundaryFieldRef()
Return a reference to the boundary field.
const Internal::FieldType & primitiveField() const
Return a const-reference to the primitive field.
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Definition: HashTable.C:167
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
const Time & time() const
Return time.
Definition: IOobject.C:315
const word & name() const
Return name.
Definition: IOobject.H:307
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: PtrList.H:75
bool set(const label) const
Is element set.
Definition: PtrListI.H:62
A List obtained as a section of another List.
Definition: SubList.H:56
This boundary condition is not designed to be evaluated; it is assumed that the value is assigned via...
Foam::calculatedFvsPatchField.
A calculated boundary condition for pointField.
const word & name() const
Return const reference to name.
Class containing functor to negate primitives. Dummy for all other types.
Definition: flipOp.H:51
Forward field mapper.
const labelList & faceMap() const
Return face map.
const labelList & cellMap() const
Return cell map.
const labelList & patchMap() const
Return patch map.
static tmp< VolField< Type > > interpolate(const VolField< Type > &, const fvMesh &sMesh, const labelList &patchMap, const labelList &cellMap, const labelList &faceMap)
Map volume field.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:98
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:433
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:932
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:90
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:58
virtual label size() const
Return size.
Definition: fvPatch.H:147
virtual label start() const
Return start label of this patch in the polyMesh face list.
Definition: fvPatch.H:141
An abstract base class with a fat-interface to all derived classes covering all possible ways in whic...
Definition: fvsPatchField.H:86
Constraint fvPatchField to hold values for internal face exposed by sub-setting.
Constraint fvsPatchField to hold values for internal face exposed by sub-setting.
Constraint pointPatchField to hold values for internal face exposed by sub-setting.
Mesh representing a set of points created from polyMesh.
Definition: pointMesh.H:52
const objectRegistry & db() const
Return database. For now is its polyMesh.
Definition: pointMesh.H:158
const pointBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: pointMesh.H:146
Abstract base class for point-mesh patch fields.
Basic pointPatch represents a set of points from the mesh.
Definition: pointPatch.H:61
virtual const labelList & meshPoints() const =0
Return mesh points.
virtual label size() const =0
Return size.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:78
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1321
label nInternalFaces() const
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
label patchi
volScalarField sf(fieldObject, mesh)
static tmp< SurfaceField< Type > > interpolate(const VolField< Type > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
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
bool isFlux(const DimensionedField< Type, surfaceMesh > &df)
Check if surfaceField is a flux.
Definition: surfaceFields.H:54
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
Definition: HashTable.H:112
Foam::surfaceFields.