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 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 )
52 {
53  // 1. Create the complete field with dummy patch fields
54  PtrList<fvPatchField<Type>> patchFields(patchMap.size());
55 
56  forAll(patchFields, patchi)
57  {
58  // Set the first one by hand as it corresponds to the
59  // exposed internal faces. Additional interpolation can be put here
60  // as necessary.
61  if (patchMap[patchi] == -1)
62  {
63  patchFields.set
64  (
65  patchi,
66  new emptyFvPatchField<Type>
67  (
68  sMesh.boundary()[patchi],
70  )
71  );
72  }
73  else
74  {
75  patchFields.set
76  (
77  patchi,
79  (
80  calculatedFvPatchField<Type>::typeName,
81  sMesh.boundary()[patchi],
83  )
84  );
85  }
86  }
87 
88  auto tresult = tmp<GeometricField<Type, fvPatchField, volMesh>>::New
89  (
90  IOobject
91  (
92  "subset"+vf.name(),
93  sMesh.time().timeName(),
94  sMesh,
97  ),
98  sMesh,
99  vf.dimensions(),
100  Field<Type>(vf.primitiveField(), cellMap),
101  patchFields
102  );
103  auto& result = tresult.ref();
104  result.oriented() = vf.oriented();
105 
106 
107  // 2. Change the fvPatchFields to the correct type using a mapper
108  // constructor (with reference to the now correct internal field)
109 
110  auto& bf = result.boundaryFieldRef();
111 
112  forAll(bf, patchi)
113  {
114  const label basePatchId = patchMap[patchi];
115 
116  if (basePatchId != -1)
117  {
118  // Construct addressing
119  const fvPatch& subPatch = sMesh.boundary()[patchi];
120  const fvPatch& basePatch = vf.mesh().boundary()[basePatchId];
121  const label baseStart = basePatch.start();
122  const label baseSize = basePatch.size();
123 
124  labelList directAddressing(subPatch.size());
125 
126  forAll(directAddressing, i)
127  {
128  const label baseFacei = faceMap[subPatch.start()+i];
129 
130  if (baseFacei >= baseStart && baseFacei < baseStart+baseSize)
131  {
132  directAddressing[i] = baseFacei-baseStart;
133  }
134  else
135  {
136  // Mapped from internal face. Do what? Leave up to
137  // fvPatchField
138  directAddressing[i] = -1;
139  }
140  }
141 
142  bf.set
143  (
144  patchi,
146  (
147  vf.boundaryField()[basePatchId],
148  subPatch,
149  result(),
150  directFvPatchFieldMapper(directAddressing)
151  )
152  );
153  }
154  }
155 
156  return tresult;
157 }
158 
159 
160 template<class Type>
161 Foam::tmp
162 <
164 >
166 (
167  const GeometricField<Type, fvPatchField, volMesh>& vf
168 ) const
169 {
170  return interpolate
171  (
172  vf,
173  subMesh(),
174  patchMap(),
175  cellMap(),
176  faceMap()
177  );
178 }
179 
180 
181 template<class Type>
182 Foam::tmp
183 <
185 >
187 (
188  const GeometricField<Type, fvsPatchField, surfaceMesh>& vf,
189  const fvMesh& sMesh,
190  const labelUList& patchMap,
191  const labelUList& cellMap,
192  const labelUList& faceMap
193 )
194 {
195  // 1. Create the complete field with dummy patch fields
196  PtrList<fvsPatchField<Type>> patchFields(patchMap.size());
197 
198  forAll(patchFields, patchi)
199  {
200  // Set the first one by hand as it corresponds to the
201  // exposed internal faces. Additional interpolation can be put here
202  // as necessary.
203  if (patchMap[patchi] == -1)
204  {
205  patchFields.set
206  (
207  patchi,
208  new emptyFvsPatchField<Type>
209  (
210  sMesh.boundary()[patchi],
212  )
213  );
214  }
215  else
216  {
217  patchFields.set
218  (
219  patchi,
221  (
222  calculatedFvsPatchField<Type>::typeName,
223  sMesh.boundary()[patchi],
225  )
226  );
227  }
228  }
229 
230  // Create the complete field from the pieces
231  auto tresult = tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>::New
232  (
233  IOobject
234  (
235  "subset"+vf.name(),
236  sMesh.time().timeName(),
237  sMesh,
240  ),
241  sMesh,
242  vf.dimensions(),
243  Field<Type>
244  (
245  vf.primitiveField(),
246  SubList<label>(faceMap, sMesh.nInternalFaces())
247  ),
248  patchFields
249  );
250  auto& result = tresult.ref();
251  result.oriented() = vf.oriented();
252 
253 
254  // 2. Change the fvsPatchFields to the correct type using a mapper
255  // constructor (with reference to the now correct internal field)
256 
257  auto& bf = result.boundaryFieldRef();
258 
259  forAll(bf, patchi)
260  {
261  if (patchMap[patchi] != -1)
262  {
263  // Construct addressing
264  const fvPatch& subPatch = sMesh.boundary()[patchi];
265  const fvPatch& basePatch = vf.mesh().boundary()[patchMap[patchi]];
266  const label baseStart = basePatch.start();
267  const label baseSize = basePatch.size();
268 
269  labelList directAddressing(subPatch.size());
270 
271  forAll(directAddressing, i)
272  {
273  label baseFacei = faceMap[subPatch.start()+i];
274 
275  if (baseFacei >= baseStart && baseFacei < baseStart+baseSize)
276  {
277  directAddressing[i] = baseFacei-baseStart;
278  }
279  else
280  {
281  // Mapped from internal face. Do what? Leave up to
282  // patchField. This would require also to pass in
283  // original internal field so for now do as post-processing
284  directAddressing[i] = -1;
285  }
286  }
287 
288  bf.set
289  (
290  patchi,
292  (
293  vf.boundaryField()[patchMap[patchi]],
294  subPatch,
295  result(),
296  directFvPatchFieldMapper(directAddressing)
297  )
298  );
299 
300 
301  // Post-process patch field for exposed faces
302 
303  fvsPatchField<Type>& pfld = bf[patchi];
304  const labelUList& fc = bf[patchi].patch().faceCells();
305  const labelList& own = vf.mesh().faceOwner();
306 
307  forAll(pfld, i)
308  {
309  label baseFacei = faceMap[subPatch.start()+i];
310  if (baseFacei < vf.primitiveField().size())
311  {
312  Type val = vf.internalField()[baseFacei];
313 
314  if (cellMap[fc[i]] == own[baseFacei] || !vf.oriented()())
315  {
316  pfld[i] = val;
317  }
318  else
319  {
320  pfld[i] = flipOp()(val);
321  }
322  }
323  else
324  {
325  // Exposed face from other patch.
326  // Only possible in case of a coupled boundary
327  label patchi = vf.mesh().boundaryMesh().whichPatch
328  (
329  baseFacei
330  );
331  const fvPatch& otherPatch = vf.mesh().boundary()[patchi];
332  label patchFacei = otherPatch.patch().whichFace(baseFacei);
333  pfld[i] = vf.boundaryField()[patchi][patchFacei];
334  }
335  }
336  }
337  }
338 
339  return tresult;
340 }
341 
342 
343 template<class Type>
344 Foam::tmp
345 <
347 >
349 (
350  const GeometricField<Type, fvsPatchField, surfaceMesh>& sf
351 ) const
352 {
353  return interpolate
354  (
355  sf,
356  subMesh(),
357  patchMap(),
358  cellMap(),
359  faceMap()
360  );
361 }
362 
363 
364 template<class Type>
365 Foam::tmp
366 <
368 >
370 (
371  const GeometricField<Type, pointPatchField, pointMesh>& vf,
372  const pointMesh& sMesh,
373  const labelUList& patchMap,
374  const labelUList& pointMap
375 )
376 {
377  // 1. Create the complete field with dummy patch fields
378  PtrList<pointPatchField<Type>> patchFields(patchMap.size());
379 
380  forAll(patchFields, patchi)
381  {
382  // Set the first one by hand as it corresponds to the
383  // exposed internal faces. Additional interpolation can be put here
384  // as necessary.
385  if (patchMap[patchi] == -1)
386  {
387  patchFields.set
388  (
389  patchi,
390  new emptyPointPatchField<Type>
391  (
392  sMesh.boundary()[patchi],
394  )
395  );
396  }
397  else
398  {
399  patchFields.set
400  (
401  patchi,
403  (
404  calculatedPointPatchField<Type>::typeName,
405  sMesh.boundary()[patchi],
407  )
408  );
409  }
410  }
411 
412  // Create the complete field from the pieces
413  auto tresult = tmp<GeometricField<Type, pointPatchField, pointMesh>>::New
414  (
415  IOobject
416  (
417  "subset"+vf.name(),
418  sMesh.time().timeName(),
419  sMesh.thisDb(),
422  ),
423  sMesh,
424  vf.dimensions(),
425  Field<Type>(vf.primitiveField(), pointMap),
426  patchFields
427  );
428  auto& result = tresult.ref();
429  result.oriented() = vf.oriented();
430 
431 
432  // 2. Change the pointPatchFields to the correct type using a mapper
433  // constructor (with reference to the now correct internal field)
434 
435  auto& bf = result.boundaryFieldRef();
436 
437  forAll(bf, patchi)
438  {
439  // Set the first one by hand as it corresponds to the
440  // exposed internal faces. Additional interpolation can be put here
441  // as necessary.
442  if (patchMap[patchi] != -1)
443  {
444  // Construct addressing
445  const pointPatch& basePatch =
446  vf.mesh().boundary()[patchMap[patchi]];
447 
448  const labelList& meshPoints = basePatch.meshPoints();
449 
450  // Make addressing from mesh to patch point
451  Map<label> meshPointMap(2*meshPoints.size());
452  forAll(meshPoints, localI)
453  {
454  meshPointMap.insert(meshPoints[localI], localI);
455  }
456 
457  // Find which subpatch points originate from which patch point
458  const pointPatch& subPatch = sMesh.boundary()[patchi];
459  const labelList& subMeshPoints = subPatch.meshPoints();
460 
461  // If mapped from outside patch leave handling up to patchField
462  labelList directAddressing(subPatch.size(), -1);
463 
464  forAll(subMeshPoints, localI)
465  {
466  // Get mesh point on original mesh.
467  label meshPointi = pointMap[subMeshPoints[localI]];
468 
469  const auto iter = meshPointMap.cfind(meshPointi);
470 
471  if (iter.found())
472  {
473  directAddressing[localI] = *iter;
474  }
475  }
476 
477  bf.set
478  (
479  patchi,
481  (
482  vf.boundaryField()[patchMap[patchi]],
483  subPatch,
484  result(),
485  directPointPatchFieldMapper(directAddressing)
486  )
487  );
488  }
489  }
490 
491  return tresult;
492 }
493 
494 
495 template<class Type>
496 Foam::tmp
497 <
499 >
501 (
502  const GeometricField<Type, pointPatchField, pointMesh>& sf
503 ) const
504 {
505  return interpolate
506  (
507  sf,
508  pointMesh::New(subMesh()), // subsetted point mesh
509  patchMap(),
510  pointMap()
511  );
512 }
513 
514 
515 template<class Type>
516 Foam::tmp
517 <
519 >
521 (
522  const DimensionedField<Type, volMesh>& df,
523  const fvMesh& sMesh,
524  const labelUList& cellMap
525 )
526 {
527  auto tresult = tmp<DimensionedField<Type, volMesh>>::New
528  (
529  IOobject
530  (
531  "subset"+df.name(),
532  sMesh.time().timeName(),
533  sMesh,
536  ),
537  sMesh,
538  df.dimensions(),
539  Field<Type>(df, cellMap)
540  );
541  tresult.ref().oriented() = df.oriented();
542 
543  return tresult;
544 }
545 
546 
547 template<class Type>
548 Foam::tmp
549 <
551 >
553 (
554  const DimensionedField<Type, volMesh>& df
555 ) const
556 {
557  return interpolate(df, subMesh(), cellMap());
558 }
559 
560 
561 // ************************************************************************* //
Foam::IOobject::NO_WRITE
Definition: IOobject.H:130
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:71
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:59
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
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:94
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)
Map volume field.
Foam::List::set
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:325
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:80
Foam::GeometricField< Type, Foam::fvPatchField, Foam::volMesh >
Foam::IOobject::NO_READ
Definition: IOobject.H:123
Foam::DimensionedField< Type, Foam::volMesh >