fvMeshStitcherToolsTemplates.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) 2023 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 "fvMeshStitcherTools.H"
27 #include "surfaceFields.H"
28 #include "coupledFvPatch.H"
29 #include "nonConformalBoundary.H"
30 #include "nonConformalFvPatch.H"
32 
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
34 
35 template<class Type>
37 (
38  const Field<Type>& f,
39  const labelUList& addr,
40  const label addr0
41 )
42 {
43  tmp<Field<Type>> tresult(new Field<Type>(addr.size()));
44  forAll(addr, i)
45  {
46  tresult.ref()[i] = f[addr[i] - addr0];
47  }
48  return tresult;
49 }
50 
51 
52 template<class Type>
54 (
55  const tmp<Field<Type>>& f,
56  const labelUList& addr,
57  const label addr0
58 )
59 {
60 
61  tmp<Field<Type>> tresult = fieldMap(f(), addr, addr0);
62  f.clear();
63  return tresult;
64 }
65 
66 
67 template<class Type>
69 (
70  const Field<Type>& f,
71  const label size,
72  const labelUList& addr,
73  const label addr0
74 )
75 {
76  tmp<Field<Type>> tresult(new Field<Type>(size, Zero));
77  forAll(addr, i)
78  {
79  tresult.ref()[addr[i] - addr0] += f[i];
80  }
81  return tresult;
82 }
83 
84 
85 template<class Type>
87 (
88  const tmp<Field<Type>>& f,
89  const label size,
90  const labelUList& addr,
91  const label addr0
92 )
93 {
94  tmp<Field<Type>> tresult = fieldRMapSum(f(), size, addr, addr0);
95  f.clear();
96  return tresult;
97 }
98 
99 
100 template<class Type>
103 (
104  const SurfaceFieldBoundary<Type>& fieldb
105 )
106 {
107  const bool isFluxField = isFlux(fieldb[0].internalField());
108 
109  const fvBoundaryMesh& fvbm = fieldb[0].patch().boundaryMesh();
110 
111  tmp<SurfaceFieldBoundary<Type>> tncFieldb
112  (
113  new SurfaceFieldBoundary<Type>
114  (
115  SurfaceField<Type>::Internal::null(),
116  fieldb
117  )
118  );
119  SurfaceFieldBoundary<Type>& ncFieldb = tncFieldb.ref();
120 
121  ncFieldb == pTraits<Type>::zero;
122 
123  const surfaceScalarField::Boundary origNcMagSfb
124  (
125  surfaceScalarField::Internal::null(),
127  );
128 
129  const labelList origPatchIndices =
130  nonConformalBoundary::New(fvbm.mesh()).allOrigPatchIndices();
131 
132  // Accumulate the non-conformal parts of the field into the original faces
133  forAll(fvbm, ncPatchi)
134  {
135  const fvPatch& fvp = fvbm[ncPatchi];
136 
137  if (!isA<nonConformalFvPatch>(fvp)) continue;
138 
139  const nonConformalFvPatch& ncFvp =
140  refCast<const nonConformalFvPatch>(fvbm[ncPatchi]);
141 
142  const label origPatchi = ncFvp.origPatchIndex();
143  const fvPatch& origFvp = ncFvp.origPatch();
144 
145  const scalarField& ncNcMagSf = ncFvp.patch().magSf();
146 
147  // Sum properties with an area-weight, unless this is a flux. Fluxes
148  // already scale with the area.
149  ncFieldb[origPatchi] +=
151  (
152  isFluxField ? fieldb[ncPatchi] : ncNcMagSf*fieldb[ncPatchi],
153  origFvp.size(),
154  ncFvp.polyFaces(),
155  origFvp.start()
156  );
157  }
158 
159  // Scale or average as appropriate
160  forAll(origPatchIndices, i)
161  {
162  const label origPatchi = origPatchIndices[i];
163  const fvPatch& origFvp = fvbm[origPatchi];
164 
165  // If this is a flux then scale to the total size of the face
166  if (isFluxField)
167  {
168  const scalarField origTotalMagSf
169  (
170  origFvp.magSf() + origNcMagSfb[origPatchi]
171  );
172 
173  ncFieldb[origPatchi] *=
174  origTotalMagSf
175  /max(origNcMagSfb[origPatchi], small*origTotalMagSf);
176  }
177  // If this is not a flux then divide by the area to create an
178  // area-weighted average
179  else
180  {
181  ncFieldb[origPatchi] /=
182  max(origNcMagSfb[origPatchi], vSmall);
183  }
184  }
185 
186  return tncFieldb;
187 }
188 
189 
190 template<class Type>
193 (
194  const SurfaceFieldBoundary<Type>& fieldb
195 )
196 {
197  const bool isFluxField = isFlux(fieldb[0].internalField());
198 
199  const fvBoundaryMesh& fvbm = fieldb[0].patch().boundaryMesh();
200 
201  tmp<SurfaceFieldBoundary<Type>> torigFieldb
202  (
203  new SurfaceFieldBoundary<Type>
204  (
205  SurfaceField<Type>::Internal::null(),
206  fieldb
207  )
208  );
209  SurfaceFieldBoundary<Type>& origFieldb = torigFieldb.ref();
210 
211  const surfaceScalarField::Boundary origNcMagSfb
212  (
213  surfaceScalarField::Internal::null(),
215  );
216 
217  const labelList origPatchIndices =
218  nonConformalBoundary::New(fvbm.mesh()).allOrigPatchIndices();
219 
220  // Scale or average as appropriate
221  forAll(origPatchIndices, i)
222  {
223  const label origPatchi = origPatchIndices[i];
224  const fvPatch& origFvp = fvbm[origPatchi];
225 
226  // If this is a flux then scale to the total size of the face
227  if (isFluxField)
228  {
229  const scalarField origTotalMagSf
230  (
231  origFvp.magSf() + origNcMagSfb[origPatchi]
232  );
233 
234  origFieldb[origPatchi] *=
235  origTotalMagSf
236  /max(origFvp.magSf(), small*origTotalMagSf);
237  }
238  }
239 
240  return torigFieldb;
241 }
242 
243 
244 template<class Type>
247 (
248  const SurfaceFieldBoundary<Type>& ncFieldb,
249  const SurfaceFieldBoundary<Type>& origFieldb
250 )
251 {
252  const bool isFluxField = isFlux(origFieldb[0].internalField());
253 
254  const fvBoundaryMesh& fvbm = origFieldb[0].patch().boundaryMesh();
255 
256  const surfaceScalarField::Boundary& magSfb =
257  fvbm.mesh().magSf().boundaryField();
258 
259  // Initialise the result and copy the original fields
260  tmp<SurfaceFieldBoundary<Type>> tfieldb
261  (
262  new SurfaceFieldBoundary<Type>
263  (
264  SurfaceField<Type>::Internal::null(),
265  origFieldb
266  )
267  );
268  SurfaceFieldBoundary<Type>& fieldb = tfieldb.ref();
269 
270  // Map the conformed non-conformal values into the non-conformal patch
271  // fields
272  forAll(fvbm, ncPatchi)
273  {
274  const fvPatch& fvp = fvbm[ncPatchi];
275 
276  if (!isA<nonConformalFvPatch>(fvp)) continue;
277 
278  const nonConformalFvPatch& ncFvp =
279  refCast<const nonConformalFvPatch>(fvp);
280 
281  const label origPatchi = ncFvp.origPatchIndex();
282  const fvPatch& origFvp = ncFvp.origPatch();
283 
284  fieldb[ncPatchi] =
286  (
287  ncFieldb[origPatchi],
288  ncFvp.polyFaces(),
289  origFvp.start()
290  );
291  }
292 
293  const labelList origPatchIndices =
294  nonConformalBoundary::New(fvbm.mesh()).allOrigPatchIndices();
295 
296  // If a flux then scale down to the part face area
297  if (isFluxField)
298  {
299  const surfaceScalarField::Boundary origNcMagSfb
300  (
301  surfaceScalarField::Internal::null(),
303  );
304 
305  // Scale the original patch fields
306  forAll(origPatchIndices, i)
307  {
308  const label origPatchi = origPatchIndices[i];
309 
310  const scalarField origTotalMagSf
311  (
312  magSfb[origPatchi] + origNcMagSfb[origPatchi]
313  );
314 
315  fieldb[origPatchi] *= magSfb[origPatchi]/origTotalMagSf;
316  }
317 
318  // Scale the non-conformal patch fields
319  forAll(fvbm, ncPatchi)
320  {
321  const fvPatch& fvp = fvbm[ncPatchi];
322 
323  if (!isA<nonConformalFvPatch>(fvp)) continue;
324 
325  const nonConformalFvPatch& ncFvp =
326  refCast<const nonConformalFvPatch>(fvp);
327 
328  const label origPatchi = ncFvp.origPatchIndex();
329  const fvPatch& origFvp = ncFvp.origPatch();
330 
331  const scalarField ncTotalMagSf
332  (
334  (
335  magSfb[origPatchi] + origNcMagSfb[origPatchi],
336  ncFvp.polyFaces(),
337  origFvp.start()
338  )
339  );
340 
341  fieldb[ncPatchi] *= magSfb[ncPatchi]/ncTotalMagSf;
342  }
343  }
344 
345  // Overwrite error values
346  forAll(fvbm, errorPatchi)
347  {
348  const fvPatch& fvp = fvbm[errorPatchi];
349 
350  if (!isA<nonConformalErrorFvPatch>(fvp)) continue;
351 
352  const nonConformalErrorFvPatch& errorFvp =
353  refCast<const nonConformalErrorFvPatch>(fvp);
354 
355  const label origPatchi = errorFvp.origPatchIndex();
356  const fvPatch& origFvp = errorFvp.origPatch();
357 
358  if (isFluxField)
359  {
360  fieldb[errorPatchi] = Zero;
361  }
362  else
363  {
364  fieldb[errorPatchi] =
366  (
367  origFieldb[origPatchi],
368  errorFvp.polyFaces(),
369  origFvp.start()
370  );
371  }
372  }
373 
374  return tfieldb;
375 }
376 
377 
378 template<class Type>
381 (
382  const SurfaceFieldBoundary<Type>& fieldb,
383  const bool flip,
384  const scalar ownerWeight,
385  const scalar neighbourWeight
386 )
387 {
388  const fvBoundaryMesh& fvbm = fieldb[0].patch().boundaryMesh();
389 
390  tmp<SurfaceFieldBoundary<Type>> tsyncFieldb
391  (
392  new SurfaceFieldBoundary<Type>
393  (
394  SurfaceField<Type>::Internal::null(),
395  fieldb
396  )
397  );
398  SurfaceFieldBoundary<Type>& syncFieldb = tsyncFieldb.ref();
399 
400  SurfaceFieldBoundary<Type> fieldbNbr
401  (
402  SurfaceField<Type>::Internal::null(),
403  fieldb.boundaryNeighbourField()
404  );
405 
406  forAll(fvbm, patchi)
407  {
408  const fvPatch& fvp = fvbm[patchi];
409 
410  if (!fvp.coupled()) continue;
411 
412  const coupledFvPatch& cFvp = refCast<const coupledFvPatch>(fvp);
413 
414  const scalar w = cFvp.owner() ? ownerWeight : neighbourWeight;
415  const scalar v = cFvp.owner() ? neighbourWeight : ownerWeight;
416 
417  syncFieldb[patchi] =
418  w*syncFieldb[patchi] + (flip ? -v : +v)*fieldbNbr[patchi];
419  }
420 
421  return tsyncFieldb;
422 }
423 
424 
425 template<class Type>
428 (
429  const SurfaceFieldBoundary<Type>& fieldb
430 )
431 {
432  const bool isFluxField = isFlux(fieldb[0].internalField());
433 
434  return synchronisedBoundaryField<Type>
435  (
436  fieldb,
437  isFluxField,
438  0.5,
439  0.5
440  );
441 }
442 
443 
444 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
A class for managing temporary objects.
Definition: tmp.H:55
volScalarField scalarField(fieldObject, mesh)
label patchi
autoPtr< CompressibleMomentumTransportModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const viscosity &viscosity)
tmp< SurfaceFieldBoundary< scalar > > origNcMagSfb(const fvMesh &mesh)
Return the total non-conformal area associated with each original face.
tmp< SurfaceFieldBoundary< Type > > conformedNcBoundaryField(const SurfaceFieldBoundary< Type > &fieldb)
Extract the non-conformal parts of the boundary field and store it on the.
tmp< Field< Type > > fieldMap(const Field< Type > &f, const labelUList &addr, const label addr0=0)
Map a field with an (optional) addressing offset.
tmp< Field< Type > > fieldRMapSum(const Field< Type > &f, const label size, const labelUList &addr, const label addr0=0)
Reverse map a field with an (optional) addressing offset, initialising the.
tmp< SurfaceFieldBoundary< Type > > synchronisedBoundaryField(const SurfaceFieldBoundary< Type > &fieldb, const bool flip, const scalar ownerWeight, const scalar neighbourWeight)
Synchronise the boundary field by combining corresponding.
tmp< SurfaceFieldBoundary< Type > > unconformedBoundaryField(const SurfaceFieldBoundary< Type > &ncFieldb, const SurfaceFieldBoundary< Type > &origFieldb)
Combine non-conformal and original parts of the boundary field from the.
tmp< SurfaceFieldBoundary< Type > > conformedOrigBoundaryField(const SurfaceFieldBoundary< Type > &fieldb)
Extract the original parts of the boundary field and store it.
static const zero Zero
Definition: zero.H:97
List< label > labelList
A List of labels.
Definition: labelList.H:56
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:55
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
UList< label > labelUList
Definition: UList.H:65
labelList f(nPoints)
Foam::surfaceFields.