edgeInterpolationScheme.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) 2016-2017 Wikki Ltd
9  Copyright (C) 2019-2021 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 
30 #include "areaFields.H"
31 #include "edgeFields.H"
33 
34 // * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
35 
36 template<class Type>
39 (
40  const faMesh& mesh,
41  Istream& schemeData
42 )
43 {
45  {
47  << "constructing edgeInterpolationScheme<Type>"
48  << endl;
49  }
50 
51  if (schemeData.eof())
52  {
53  FatalIOErrorInFunction(schemeData)
54  << "Discretisation scheme not specified" << nl << nl
55  << "Valid schemes are :" << nl
56  << MeshConstructorTablePtr_->sortedToc()
57  << exit(FatalIOError);
58  }
59 
60  const word schemeName(schemeData);
61 
62  auto* ctorPtr = MeshConstructorTable(schemeName);
63 
64  if (!ctorPtr)
65  {
67  (
68  schemeData,
69  "discretisation",
70  schemeName,
71  *MeshConstructorTablePtr_
72  ) << exit(FatalIOError);
73  }
74 
75  return ctorPtr(mesh, schemeData);
76 }
77 
78 
79 template<class Type>
82 (
83  const faMesh& mesh,
84  const edgeScalarField& faceFlux,
85  Istream& schemeData
86 )
87 {
89  {
91  << "constructing edgeInterpolationScheme<Type>"
92  << endl;
93  }
94 
95  if (schemeData.eof())
96  {
97  FatalIOErrorInFunction(schemeData)
98  << "Discretisation scheme not specified"
99  << endl << endl
100  << "Valid schemes are :" << endl
101  << MeshConstructorTablePtr_->sortedToc()
102  << exit(FatalIOError);
103  }
104 
105  const word schemeName(schemeData);
106 
107  auto* ctorPtr = MeshFluxConstructorTable(schemeName);
108 
109  if (!ctorPtr)
110  {
112  (
113  schemeData,
114  "discretisation",
115  schemeName,
116  *MeshFluxConstructorTablePtr_
117  ) << exit(FatalIOError);
118  }
119 
120  return ctorPtr(mesh, faceFlux, schemeData);
121 }
122 
123 
124 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
125 
126 template<class Type>
128 {}
130 
131 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
132 
133 template<class Type>
136 (
138  const tmp<edgeScalarField>& tlambdas,
139  const tmp<edgeScalarField>& tys
140 )
141 {
143  {
145  << "interpolating "
146  << vf.type() << " "
147  << vf.name()
148  << " from areas to edges "
149  "without explicit correction"
150  << endl;
151  }
152 
153  const edgeScalarField& lambdas = tlambdas();
154  const edgeScalarField& ys = tys();
155 
156  const Field<Type>& vfi = vf.internalField();
157  const scalarField& lambda = lambdas.internalField();
158  const scalarField& y = ys.internalField();
159 
160  const faMesh& mesh = vf.mesh();
161  const labelUList& P = mesh.owner();
162  const labelUList& N = mesh.neighbour();
163 
165  (
167  (
168  IOobject
169  (
170  "interpolate("+vf.name()+')',
171  vf.instance(),
172  vf.db()
173  ),
174  mesh,
175  vf.dimensions()
176  )
177  );
179 
180  Field<Type>& sfi = sf.primitiveFieldRef();
181 
182  for (label fi=0; fi<P.size(); ++fi)
183  {
184  const tensorField& curT = mesh.edgeTransformTensors()[fi];
185 
186  const tensor& Te = curT[0];
187  const tensor& TP = curT[1];
188  const tensor& TN = curT[2];
189 
190  sfi[fi] =
191  transform
192  (
193  Te.T(),
194  lambda[fi]*transform(TP, vfi[P[fi]])
195  + y[fi]*transform(TN, vfi[N[fi]])
196  );
197  }
198 
199 
200  // Interpolate across coupled patches using given lambdas and ys
201 
202  forAll(lambdas.boundaryField(), pi)
203  {
204  const faePatchScalarField& pLambda = lambdas.boundaryField()[pi];
205  const faePatchScalarField& pY = ys.boundaryField()[pi];
206 
207  if (vf.boundaryField()[pi].coupled())
208  {
209  label size = vf.boundaryField()[pi].patch().size();
210  label start = vf.boundaryField()[pi].patch().start();
211 
212  Field<Type> pOwnVf(vf.boundaryField()[pi].patchInternalField());
213  Field<Type> pNgbVf(vf.boundaryField()[pi].patchNeighbourField());
214 
215  Field<Type>& pSf = sf.boundaryFieldRef()[pi];
216 
217  for (label i=0; i<size; ++i)
218  {
219  const tensorField& curT =
220  mesh.edgeTransformTensors()[start + i];
221 
222  const tensor& Te = curT[0];
223  const tensor& TP = curT[1];
224  const tensor& TN = curT[2];
225 
226  pSf[i] =
227  transform
228  (
229  Te.T(),
230  pLambda[i]*transform(TP, pOwnVf[i])
231  + pY[i]*transform(TN, pNgbVf[i])
232  );
233  }
234 
235 // sf.boundaryFieldRef()[pi] =
236 // pLambda*vf.boundaryField()[pi].patchInternalField()
237 // + pY*vf.boundaryField()[pi].patchNeighbourField();
238  }
239  else
240  {
241  sf.boundaryFieldRef()[pi] = vf.boundaryField()[pi];
242  }
243  }
244 
245  tlambdas.clear();
246  tys.clear();
247 
248  return tsf;
249 }
250 
251 
252 template<class Type>
255 (
257  const tmp<edgeScalarField>& tlambdas
258 )
259 {
261  {
263  << "interpolating "
264  << vf.type() << " "
265  << vf.name()
266  << " from area to edges "
267  "without explicit correction"
268  << endl;
269  }
270 
271  const edgeScalarField& lambdas = tlambdas();
272 
273  const Field<Type>& vfi = vf.internalField();
274  const scalarField& lambda = lambdas.internalField();
275 
276  const faMesh& mesh = vf.mesh();
277  const labelUList& P = mesh.owner();
278  const labelUList& N = mesh.neighbour();
279 
280  tmp<GeometricField<Type, faePatchField, edgeMesh>> tsf
281  (
282  new GeometricField<Type, faePatchField, edgeMesh>
283  (
284  IOobject
285  (
286  "interpolate("+vf.name()+')',
287  vf.instance(),
288  vf.db()
289  ),
290  mesh,
291  vf.dimensions()
292  )
293  );
294  GeometricField<Type, faePatchField, edgeMesh>& sf = tsf.ref();
295 
296  Field<Type>& sfi = sf.primitiveFieldRef();
297 
298  for (label eI = 0; eI < P.size(); ++eI)
299  {
300  const tensorField& curT = mesh.edgeTransformTensors()[eI];
301 
302  const tensor& Te = curT[0];
303  const tensor& TP = curT[1];
304  const tensor& TN = curT[2];
305 
306  sfi[eI] =
307  transform
308  (
309  Te.T(),
310  lambda[eI]*transform(TP, vfi[P[eI]])
311  + (1 - lambda[eI])*transform(TN, vfi[N[eI]])
312  );
313  }
314 
315 
316  // Interpolate across coupled patches using given lambdas
317 
318  const auto& vfb = vf.boundaryField();
319 
320  forAll(lambdas.boundaryField(), pi)
321  {
322  const faePatchScalarField& pLambda = lambdas.boundaryField()[pi];
323 
324  if (vf.boundaryField()[pi].coupled())
325  {
326  label size = vfb[pi].patch().size();
327  label start = vfb[pi].patch().start();
328 
329  Field<Type> pOwnVf(vfb[pi].patchInternalField());
330  Field<Type> pNgbVf(vfb[pi].patchNeighbourField());
331 
332  Field<Type>& pSf = sf.boundaryFieldRef()[pi];
333 
334  for (label i=0; i<size; ++i)
335  {
336  const tensorField& curT =
337  mesh.edgeTransformTensors()[start + i];
338 
339  const tensor& Te = curT[0];
340  const tensor& TP = curT[1];
341  const tensor& TN = curT[2];
342 
343  pSf[i] =
344  transform
345  (
346  Te.T(),
347  pLambda[i]*transform(TP, pOwnVf[i])
348  + (1 - pLambda[i])*transform(TN, pNgbVf[i])
349  );
350  }
351 
352 // tsf().boundaryFieldRef()[pi] =
353 // pLambda*vf.boundaryField()[pi].patchInternalField()
354 // + (1 - pLambda)*vf.boundaryField()[pi].patchNeighbourField();
355  }
356  else
357  {
358  sf.boundaryFieldRef()[pi] = vf.boundaryField()[pi];
359  }
360  }
361 
362  tlambdas.clear();
363 
364  return tsf;
365 }
366 
367 
368 template<class Type>
371 (
373  const tmp<edgeScalarField>& tlambdas
374 )
375 {
377  {
379  << "interpolating "
380  << vf.type() << " "
381  << vf.name()
382  << " from area to edges "
383  "without explicit correction"
384  << endl;
385  }
386 
387  const edgeScalarField& lambdas = tlambdas();
388 
389  const Field<Type>& vfi = vf.internalField();
390  const scalarField& lambda = lambdas.internalField();
391 
392  const faMesh& mesh = vf.mesh();
393  const labelUList& P = mesh.owner();
394  const labelUList& N = mesh.neighbour();
395 
396  tmp<GeometricField<Type, faePatchField, edgeMesh>> tsf
397  (
398  new GeometricField<Type, faePatchField, edgeMesh>
399  (
400  IOobject
401  (
402  "interpolate("+vf.name()+')',
403  vf.instance(),
404  vf.db()
405  ),
406  mesh,
407  vf.dimensions()
408  )
409  );
410  GeometricField<Type, faePatchField, edgeMesh>& sf = tsf.ref();
411 
412  Field<Type>& sfi = sf.primitiveFieldRef();
413 
414  for (label eI = 0; eI < P.size(); ++eI)
415  {
416  sfi[eI] = lambda[eI]*vfi[P[eI]] + (1 - lambda[eI])*vfi[N[eI]];
417  }
418 
419 
420  // Interpolate across coupled patches using given lambdas
421 
422  forAll(lambdas.boundaryField(), pi)
423  {
424  const faePatchScalarField& pLambda = lambdas.boundaryField()[pi];
425 
426  if (vf.boundaryField()[pi].coupled())
427  {
428  tsf.ref().boundaryFieldRef()[pi] =
429  pLambda*vf.boundaryField()[pi].patchInternalField()
430  + (1.0 - pLambda)*vf.boundaryField()[pi].patchNeighbourField();
431  }
432  else
433  {
434  sf.boundaryFieldRef()[pi] = vf.boundaryField()[pi];
435  }
436  }
437 
438  tlambdas.clear();
439 
440  return tsf;
441 }
442 
443 
444 template<class Type>
447 (
449 ) const
450 {
452  {
454  << "interpolating "
455  << vf.type() << " "
456  << vf.name()
457  << " from areas to edges"
458  << endl;
459  }
460 
461  tmp<GeometricField<Type, faePatchField, edgeMesh>> tsf =
462  interpolate(vf, weights(vf));
463 
464  if (corrected())
465  {
466  tsf.ref() += correction(vf);
467  }
468 
469  return tsf;
470 }
471 
472 
473 template<class Type>
476 (
478 ) const
479 {
481  {
483  << "interpolating "
484  << vf.type() << " "
485  << vf.name()
486  << " from area to edges "
487  << endl;
488  }
489 
490  tmp<GeometricField<Type, faePatchField, edgeMesh>> tsf =
491  euclidianInterpolate(vf, weights(vf));
492 
493  return tsf;
494 }
495 
496 
497 template<class Type>
500 (
502 ) const
503 {
505  interpolate(tvf());
506  tvf.clear();
507  return tinterpVf;
508 }
509 
510 
511 // ************************************************************************* //
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition: faMesh.H:133
tmp< fvMatrix< Type > > correction(const fvMatrix< Type > &)
Return the correction form of the given matrix by subtracting the matrix multiplied by the current fi...
static tmp< GeometricField< Type, faePatchField, edgeMesh > > euclidianInterpolate(const GeometricField< Type, faPatchField, areaMesh > &, const tmp< edgeScalarField > &)
Return the euclidian edge-interpolate of the given area field.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: tmpI.H:235
static tmp< GeometricField< Type, faePatchField, edgeMesh > > interpolate(const GeometricField< Type, faPatchField, areaMesh > &tvf, const edgeScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
const Internal & internalField() const noexcept
Return a const-reference to the dimensioned internal field.
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Tensor< scalar > tensor
Definition: symmTensor.H:57
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
static tmp< edgeInterpolationScheme< Type > > New(const faMesh &mesh, Istream &schemeData)
Return new tmp interpolation scheme.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
scalar y
dynamicFvMesh & mesh
Generic templated field type.
Definition: Field.H:62
dimensionedScalar lambda("lambda", dimTime/sqr(dimLength), laminarTransport)
A class for handling words, derived from Foam::string.
Definition: word.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition: IOobject.C:450
constexpr scalar pi(M_PI)
GeometricField< scalar, faePatchField, edgeMesh > edgeScalarField
Definition: edgeFieldsFwd.H:43
const Mesh & mesh() const noexcept
Return mesh.
int debug
Static debugging option.
faePatchField< scalar > faePatchScalarField
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:266
const Vector< label > N(dict.get< Vector< label >>("N"))
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field values.
static tmp< GeometricField< Type, faePatchField, edgeMesh > > interpolate(const GeometricField< Type, faPatchField, areaMesh > &, const tmp< edgeScalarField > &, const tmp< edgeScalarField > &)
Return the face-interpolate of the given cell field.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:637
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
faePatchField<Type> abstract base class. This class gives a fat-interface to all derived classes cove...
Definition: edgeFieldsFwd.H:43
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition: tmpI.H:289
A class for managing temporary objects.
Definition: HashPtrTable.H:50
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:521
Tensor of scalars, i.e. Tensor<scalar>.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition: error.H:645
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
bool eof() const noexcept
True if end of input seen.
Definition: IOstream.H:289
const dimensionSet & dimensions() const noexcept
Return dimensions.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
#define InfoInFunction
Report an information message using Foam::Info.