Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
11License
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 "coupledFaPatchField.H"
33
34// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
35
36template<class Type>
39(
40 const faMesh& mesh,
41 Istream& schemeData
42)
43{
44 if (edgeInterpolation::debug)
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()
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 }
75 return ctorPtr(mesh, schemeData);
76}
77
78
79template<class Type>
82(
83 const faMesh& mesh,
84 const edgeScalarField& faceFlux,
85 Istream& schemeData
86)
87{
88 if (edgeInterpolation::debug)
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}
123
124// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
125
126template<class Type>
129
130
131// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
132
133template<class Type>
136(
138 const tmp<edgeScalarField>& tlambdas,
139 const tmp<edgeScalarField>& tys
140)
142 if (edgeInterpolation::debug)
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 (
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] =
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] =
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();
248 return tsf;
249}
250
251
252template<class Type>
255(
257 const tmp<edgeScalarField>& tlambdas
258)
259{
260 if (edgeInterpolation::debug)
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] =
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();
364 return tsf;
365}
366
367
368template<class Type>
371(
373 const tmp<edgeScalarField>& tlambdas
374)
375{
376 if (edgeInterpolation::debug)
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();
440 return tsf;
441}
442
443
444template<class Type>
447(
449) const
450{
451 if (edgeInterpolation::debug)
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 }
469 return tsf;
470}
471
472
473template<class Type>
476(
478) const
479{
480 if (edgeInterpolation::debug)
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));
502) const
503{
505 interpolate(tvf());
506 tvf.clear();
507 return tinterpVf;
508}
509
510
511// ************************************************************************* //
scalar y
constexpr scalar pi(M_PI)
const Mesh & mesh() const noexcept
Return const reference to mesh.
const dimensionSet & dimensions() const noexcept
Return dimensions.
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition Field.H:172
Generic GeometricField class.
Internal & ref(const bool updateAccessTime=true)
Same as internalFieldRef().
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field values.
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
const Internal & internalField() const noexcept
Return a const-reference to the dimensioned internal field.
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
const word & name() const noexcept
Return the object name.
Definition IOobjectI.H:205
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition IOobject.C:450
const fileName & instance() const noexcept
Read access to instance path component.
Definition IOobjectI.H:289
bool eof() const noexcept
True if end of input seen.
Definition IOstream.H:289
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition Istream.H:60
Tensor< Cmpt > T() const
Return non-Hermitian transpose.
Definition TensorI.H:419
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
label size() const noexcept
The number of entries in the list.
Definition UPtrListI.H:106
virtual bool corrected() const
Return true if this scheme uses an explicit correction.
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.
virtual tmp< edgeScalarField > weights(const GeometricField< Type, faPatchField, areaMesh > &) const =0
Return the interpolation weighting factors for the given field.
static tmp< edgeInterpolationScheme< Type > > New(const faMesh &mesh, Istream &schemeData)
Return new tmp interpolation scheme.
virtual tmp< GeometricField< Type, faePatchField, edgeMesh > > correction(const GeometricField< Type, faPatchField, areaMesh > &) const
Return the explicit correction to the face-interpolate.
const faMesh & mesh() const
Return mesh reference.
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.
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition faMesh.H:140
Tensor of scalars, i.e. Tensor<scalar>.
A class for managing temporary objects.
Definition tmp.H:75
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition tmpI.H:289
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition tmpI.H:235
A class for handling words, derived from Foam::string.
Definition word.H:66
mesh interpolate(rAU)
dynamicFvMesh & mesh
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition error.H:637
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
#define InfoInFunction
Report an information message using Foam::Info.
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
Tensor< scalar > tensor
Definition symmTensor.H:57
faePatchField< scalar > faePatchScalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
GeometricField< scalar, faePatchField, edgeMesh > edgeScalarField
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
dimensionedScalar lambda("lambda", dimTime/sqr(dimLength), laminarTransport)
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
const Vector< label > N(dict.get< Vector< label > >("N"))