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"
32 #include "faPatchFields.H"
33 #include "coupledFaPatchField.H"
34 #include "transform.H"
35 
36 // * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
37 
38 template<class Type>
41 (
42  const faMesh& mesh,
43  Istream& schemeData
44 )
45 {
47  {
49  << "constructing edgeInterpolationScheme<Type>"
50  << endl;
51  }
52 
53  if (schemeData.eof())
54  {
55  FatalIOErrorInFunction(schemeData)
56  << "Discretisation scheme not specified" << nl << nl
57  << "Valid schemes are :" << nl
58  << MeshConstructorTablePtr_->sortedToc()
59  << exit(FatalIOError);
60  }
61 
62  const word schemeName(schemeData);
63 
64  auto* ctorPtr = MeshConstructorTable(schemeName);
65 
66  if (!ctorPtr)
67  {
69  (
70  schemeData,
71  "discretisation",
72  schemeName,
73  *MeshConstructorTablePtr_
74  ) << exit(FatalIOError);
75  }
76 
77  return ctorPtr(mesh, schemeData);
78 }
79 
80 
81 template<class Type>
84 (
85  const faMesh& mesh,
86  const edgeScalarField& faceFlux,
87  Istream& schemeData
88 )
89 {
91  {
93  << "constructing edgeInterpolationScheme<Type>"
94  << endl;
95  }
96 
97  if (schemeData.eof())
98  {
99  FatalIOErrorInFunction(schemeData)
100  << "Discretisation scheme not specified"
101  << endl << endl
102  << "Valid schemes are :" << endl
103  << MeshConstructorTablePtr_->sortedToc()
104  << exit(FatalIOError);
105  }
106 
107  const word schemeName(schemeData);
108 
109  auto* ctorPtr = MeshFluxConstructorTable(schemeName);
110 
111  if (!ctorPtr)
112  {
114  (
115  schemeData,
116  "discretisation",
117  schemeName,
118  *MeshFluxConstructorTablePtr_
119  ) << exit(FatalIOError);
120  }
121 
122  return ctorPtr(mesh, faceFlux, schemeData);
123 }
124 
125 
126 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
127 
128 template<class Type>
130 {}
132 
133 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
134 
135 template<class Type>
138 (
140  const tmp<edgeScalarField>& tlambdas,
141  const tmp<edgeScalarField>& tys
142 )
143 {
145  {
147  << "interpolating "
148  << vf.type() << " "
149  << vf.name()
150  << " from areas to edges "
151  "without explicit correction"
152  << endl;
153  }
154 
155  const edgeScalarField& lambdas = tlambdas();
156  const edgeScalarField& ys = tys();
157 
158  const Field<Type>& vfi = vf.internalField();
159  const scalarField& lambda = lambdas.internalField();
160  const scalarField& y = ys.internalField();
161 
162  const faMesh& mesh = vf.mesh();
163  const labelUList& P = mesh.owner();
164  const labelUList& N = mesh.neighbour();
165 
167  (
169  (
170  IOobject
171  (
172  "interpolate("+vf.name()+')',
173  vf.instance(),
174  vf.db()
175  ),
176  mesh,
177  vf.dimensions()
178  )
179  );
181 
182  Field<Type>& sfi = sf.primitiveFieldRef();
183 
184  for (label fi=0; fi<P.size(); ++fi)
185  {
186  const tensorField& curT = mesh.edgeTransformTensors()[fi];
187 
188  const tensor& Te = curT[0];
189  const tensor& TP = curT[1];
190  const tensor& TN = curT[2];
191 
192  sfi[fi] =
193  transform
194  (
195  Te.T(),
196  lambda[fi]*transform(TP, vfi[P[fi]])
197  + y[fi]*transform(TN, vfi[N[fi]])
198  );
199  }
200 
201 
202  // Interpolate across coupled patches using given lambdas and ys
203 
204  forAll(lambdas.boundaryField(), pi)
205  {
206  const faePatchScalarField& pLambda = lambdas.boundaryField()[pi];
207  const faePatchScalarField& pY = ys.boundaryField()[pi];
208 
209  if (vf.boundaryField()[pi].coupled())
210  {
211  label size = vf.boundaryField()[pi].patch().size();
212  label start = vf.boundaryField()[pi].patch().start();
213 
214  Field<Type> pOwnVf = vf.boundaryField()[pi].patchInternalField();
215  Field<Type> pNgbVf = vf.boundaryField()[pi].patchNeighbourField();
216 
217  Field<Type>& pSf = sf.boundaryFieldRef()[pi];
218 
219  for (label i=0; i<size; ++i)
220  {
221  const tensorField& curT =
222  mesh.edgeTransformTensors()[start + i];
223 
224  const tensor& Te = curT[0];
225  const tensor& TP = curT[1];
226  const tensor& TN = curT[2];
227 
228  pSf[i] =
229  transform
230  (
231  Te.T(),
232  pLambda[i]*transform(TP, pOwnVf[i])
233  + pY[i]*transform(TN, pNgbVf[i])
234  );
235  }
236 
237 // sf.boundaryFieldRef()[pi] =
238 // pLambda*vf.boundaryField()[pi].patchInternalField()
239 // + pY*vf.boundaryField()[pi].patchNeighbourField();
240  }
241  else
242  {
243  sf.boundaryFieldRef()[pi] = vf.boundaryField()[pi];
244  }
245  }
246 
247  tlambdas.clear();
248  tys.clear();
249 
250  return tsf;
251 }
252 
253 
254 template<class Type>
257 (
259  const tmp<edgeScalarField>& tlambdas
260 )
261 {
263  {
265  << "interpolating "
266  << vf.type() << " "
267  << vf.name()
268  << " from area to edges "
269  "without explicit correction"
270  << endl;
271  }
272 
273  const edgeScalarField& lambdas = tlambdas();
274 
275  const Field<Type>& vfi = vf.internalField();
276  const scalarField& lambda = lambdas.internalField();
277 
278  const faMesh& mesh = vf.mesh();
279  const labelUList& P = mesh.owner();
280  const labelUList& N = mesh.neighbour();
281 
282  tmp<GeometricField<Type, faePatchField, edgeMesh>> tsf
283  (
284  new GeometricField<Type, faePatchField, edgeMesh>
285  (
286  IOobject
287  (
288  "interpolate("+vf.name()+')',
289  vf.instance(),
290  vf.db()
291  ),
292  mesh,
293  vf.dimensions()
294  )
295  );
296  GeometricField<Type, faePatchField, edgeMesh>& sf = tsf.ref();
297 
298  Field<Type>& sfi = sf.primitiveFieldRef();
299 
300  for (label eI = 0; eI < P.size(); ++eI)
301  {
302  const tensorField& curT = mesh.edgeTransformTensors()[eI];
303 
304  const tensor& Te = curT[0];
305  const tensor& TP = curT[1];
306  const tensor& TN = curT[2];
307 
308  sfi[eI] =
309  transform
310  (
311  Te.T(),
312  lambda[eI]*transform(TP, vfi[P[eI]])
313  + (1 - lambda[eI])*transform(TN, vfi[N[eI]])
314  );
315  }
316 
317 
318  // Interpolate across coupled patches using given lambdas
319 
320  const auto& vfb = vf.boundaryField();
321 
322  forAll(lambdas.boundaryField(), pi)
323  {
324  const faePatchScalarField& pLambda = lambdas.boundaryField()[pi];
325 
326  if (vf.boundaryField()[pi].coupled())
327  {
328  label size = vfb[pi].patch().size();
329  label start = vfb[pi].patch().start();
330 
331  Field<Type> pOwnVf(vfb[pi].patchInternalField());
332  Field<Type> pNgbVf(vfb[pi].patchNeighbourField());
333 
334  Field<Type>& pSf = sf.boundaryFieldRef()[pi];
335 
336  for (label i=0; i<size; ++i)
337  {
338  const tensorField& curT =
339  mesh.edgeTransformTensors()[start + i];
340 
341  const tensor& Te = curT[0];
342  const tensor& TP = curT[1];
343  const tensor& TN = curT[2];
344 
345  pSf[i] =
346  transform
347  (
348  Te.T(),
349  pLambda[i]*transform(TP, pOwnVf[i])
350  + (1 - pLambda[i])*transform(TN, pNgbVf[i])
351  );
352  }
353 
354 // tsf().boundaryFieldRef()[pi] =
355 // pLambda*vf.boundaryField()[pi].patchInternalField()
356 // + (1 - pLambda)*vf.boundaryField()[pi].patchNeighbourField();
357  }
358  else
359  {
360  sf.boundaryFieldRef()[pi] = vf.boundaryField()[pi];
361  }
362  }
363 
364  tlambdas.clear();
365 
366  return tsf;
367 }
368 
369 
370 template<class Type>
373 (
375  const tmp<edgeScalarField>& tlambdas
376 )
377 {
379  {
381  << "interpolating "
382  << vf.type() << " "
383  << vf.name()
384  << " from area to edges "
385  "without explicit correction"
386  << endl;
387  }
388 
389  const edgeScalarField& lambdas = tlambdas();
390 
391  const Field<Type>& vfi = vf.internalField();
392  const scalarField& lambda = lambdas.internalField();
393 
394  const faMesh& mesh = vf.mesh();
395  const labelUList& P = mesh.owner();
396  const labelUList& N = mesh.neighbour();
397 
398  tmp<GeometricField<Type, faePatchField, edgeMesh>> tsf
399  (
400  new GeometricField<Type, faePatchField, edgeMesh>
401  (
402  IOobject
403  (
404  "interpolate("+vf.name()+')',
405  vf.instance(),
406  vf.db()
407  ),
408  mesh,
409  vf.dimensions()
410  )
411  );
412  GeometricField<Type, faePatchField, edgeMesh>& sf = tsf.ref();
413 
414  Field<Type>& sfi = sf.primitiveFieldRef();
415 
416  for (label eI = 0; eI < P.size(); ++eI)
417  {
418  sfi[eI] = lambda[eI]*vfi[P[eI]] + (1 - lambda[eI])*vfi[N[eI]];
419  }
420 
421 
422  // Interpolate across coupled patches using given lambdas
423 
424  forAll(lambdas.boundaryField(), pi)
425  {
426  const faePatchScalarField& pLambda = lambdas.boundaryField()[pi];
427 
428  if (vf.boundaryField()[pi].coupled())
429  {
430  tsf.ref().boundaryFieldRef()[pi] =
431  pLambda*vf.boundaryField()[pi].patchInternalField()
432  + (1.0 - pLambda)*vf.boundaryField()[pi].patchNeighbourField();
433  }
434  else
435  {
436  sf.boundaryFieldRef()[pi] = vf.boundaryField()[pi];
437  }
438  }
439 
440  tlambdas.clear();
441 
442  return tsf;
443 }
444 
445 
446 template<class Type>
449 (
451 ) const
452 {
454  {
456  << "interpolating "
457  << vf.type() << " "
458  << vf.name()
459  << " from areas to edges"
460  << endl;
461  }
462 
463  tmp<GeometricField<Type, faePatchField, edgeMesh>> tsf =
464  interpolate(vf, weights(vf));
465 
466  if (corrected())
467  {
468  tsf.ref() += correction(vf);
469  }
470 
471  return tsf;
472 }
473 
474 
475 template<class Type>
478 (
480 ) const
481 {
483  {
485  << "interpolating "
486  << vf.type() << " "
487  << vf.name()
488  << " from area to edges "
489  << endl;
490  }
491 
492  tmp<GeometricField<Type, faePatchField, edgeMesh>> tsf =
493  euclidianInterpolate(vf, weights(vf));
494 
495  return tsf;
496 }
497 
498 
499 template<class Type>
502 (
504 ) const
505 {
507  interpolate(tvf());
508  tvf.clear();
509  return tinterpVf;
510 }
511 
512 
513 // ************************************************************************* //
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition: faMesh.H:87
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
Declarations for faPatchField types.
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.
3D tensor transformation operations.
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:46
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:627
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:46
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:172
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition: error.H:635
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.