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 "faPatchFields.H"
33#include "coupledFaPatchField.H"
34#include "transform.H"
35
36// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
37
38template<class Type>
41(
42 const faMesh& mesh,
43 Istream& schemeData
44)
45{
46 if (edgeInterpolation::debug)
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()
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
81template<class Type>
84(
85 const faMesh& mesh,
86 const edgeScalarField& faceFlux,
87 Istream& schemeData
88)
89{
90 if (edgeInterpolation::debug)
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
128template<class Type>
130{}
131
133// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
134
135template<class Type>
138(
140 const tmp<edgeScalarField>& tlambdas,
141 const tmp<edgeScalarField>& tys
142)
143{
144 if (edgeInterpolation::debug)
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();
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
169 (
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] =
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())
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] =
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
254template<class Type>
257(
259 const tmp<edgeScalarField>& tlambdas
260)
261{
262 if (edgeInterpolation::debug)
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
283 (
285 (
287 (
288 "interpolate("+vf.name()+')',
289 vf.instance(),
290 vf.db()
291 ),
292 mesh,
293 vf.dimensions()
294 )
295 );
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] =
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] =
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
370template<class Type>
373(
375 const tmp<edgeScalarField>& tlambdas
376)
377{
378 if (edgeInterpolation::debug)
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
399 (
401 (
403 (
404 "interpolate("+vf.name()+')',
405 vf.instance(),
406 vf.db()
407 ),
408 mesh,
409 vf.dimensions()
410 )
411 );
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
446template<class Type>
449(
451) const
452{
453 if (edgeInterpolation::debug)
454 {
456 << "interpolating "
457 << vf.type() << " "
458 << vf.name()
459 << " from areas to edges"
460 << endl;
461 }
462
464 interpolate(vf, weights(vf));
465
466 if (corrected())
467 {
468 tsf.ref() += correction(vf);
469 }
470
471 return tsf;
472}
473
474
475template<class Type>
478(
480) const
481{
482 if (edgeInterpolation::debug)
483 {
485 << "interpolating "
486 << vf.type() << " "
487 << vf.name()
488 << " from area to edges "
489 << endl;
490 }
491
493 euclidianInterpolate(vf, weights(vf));
494
495 return tsf;
496}
497
498
499template<class Type>
502(
504) const
505{
507 interpolate(tvf());
508 tvf.clear();
509 return tinterpVf;
510}
511
512
513// ************************************************************************* //
scalar y
const dimensionSet & dimensions() const
Return dimensions.
const Mesh & mesh() const
Return mesh.
Generic templated field type.
Definition: Field.H:82
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field.
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
Internal & ref(const bool updateAccessTime=true)
Return a reference to the dimensioned internal field.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
const Internal & internalField() const
Return a const-reference to the dimensioned internal field.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:65
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition: IOobject.C:500
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:196
bool eof() const noexcept
True if end of input seen.
Definition: IOstream.H:239
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:64
Tensor< Cmpt > T() const
Return non-Hermitian transpose.
Definition: TensorI.H:526
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
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:100
bool interpolate() const noexcept
Same as isPointData()
A class for managing temporary objects.
Definition: tmp.H:65
void clear() const noexcept
Definition: tmpI.H:287
T & ref() const
Definition: tmpI.H:227
A class for handling words, derived from Foam::string.
Definition: word.H:68
mesh interpolate(rAU)
dynamicFvMesh & mesh
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition: error.H:478
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
#define InfoInFunction
Report an information message using Foam::Info.
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:536
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
IOerror FatalIOError
tmp< fvMatrix< Type > > correction(const fvMatrix< Type > &)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
dimensionedScalar lambda("lambda", dimTime/sqr(dimLength), laminarTransport)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
3D tensor transformation operations.
const Vector< label > N(dict.get< Vector< label > >("N"))