cyclicAMIFvPatchField.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) 2011-2017 OpenFOAM Foundation
9 Copyright (C) 2019-2022 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
29#include "fvMatrix.H"
30#include "volFields.H"
31//#include "cylicFvPatchField.H"
32
33// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
34
35template<class Type>
37(
38 const fvPatch& p,
40)
41:
43 coupledFvPatchField<Type>(p, iF),
44 cyclicAMIPatch_(refCast<const cyclicAMIFvPatch>(p))
45{}
46
47
48template<class Type>
50(
51 const fvPatch& p,
53 const dictionary& dict
54)
55:
57 coupledFvPatchField<Type>(p, iF, dict, dict.found("value")),
58 cyclicAMIPatch_(refCast<const cyclicAMIFvPatch>(p, dict))
59{
60 if (!isA<cyclicAMIFvPatch>(p))
61 {
63 << " patch type '" << p.type()
64 << "' not constraint type '" << typeName << "'"
65 << "\n for patch " << p.name()
66 << " of field " << this->internalField().name()
67 << " in file " << this->internalField().objectPath()
69 }
70
71 if (!dict.found("value"))
72 {
73 if (this->coupled())
74 {
76 }
77 else
78 {
80 }
81 }
82}
83
84
85template<class Type>
87(
89 const fvPatch& p,
91 const fvPatchFieldMapper& mapper
92)
93:
95 coupledFvPatchField<Type>(ptf, p, iF, mapper),
96 cyclicAMIPatch_(refCast<const cyclicAMIFvPatch>(p))
97{
98 if (!isA<cyclicAMIFvPatch>(this->patch()))
99 {
101 << "' not constraint type '" << typeName << "'"
102 << "\n for patch " << p.name()
103 << " of field " << this->internalField().name()
104 << " in file " << this->internalField().objectPath()
105 << exit(FatalError);
106 }
107}
108
109
110template<class Type>
112(
114)
115:
117 coupledFvPatchField<Type>(ptf),
118 cyclicAMIPatch_(ptf.cyclicAMIPatch_)
119{}
120
121
122template<class Type>
124(
127)
128:
130 coupledFvPatchField<Type>(ptf, iF),
131 cyclicAMIPatch_(ptf.cyclicAMIPatch_)
132{}
134
135// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
136
137template<class Type>
139{
140 return cyclicAMIPatch_.coupled();
142
143
144template<class Type>
147{
148 const Field<Type>& iField = this->primitiveField();
149
150 // By pass polyPatch to get nbrId. Instead use cyclicAMIFvPatch virtual
151 // neighbPatch()
152 const cyclicAMIFvPatch& neighbPatch = cyclicAMIPatch_.neighbPatch();
153 const labelUList& nbrFaceCells = neighbPatch.faceCells();
154
155 Field<Type> pnf(iField, nbrFaceCells);
156
157 tmp<Field<Type>> tpnf;
158 if (cyclicAMIPatch_.applyLowWeightCorrection())
159 {
160 Field<Type> pnfInternal(iField, cyclicAMIPatch_.faceCells());
161
162 tpnf = cyclicAMIPatch_.interpolate(pnf, pnfInternal);
163 }
164 else
165 {
166 tpnf = cyclicAMIPatch_.interpolate(pnf);
167 }
168
169 if (doTransform())
170 {
171 tpnf.ref() = transform(forwardT(), tpnf());
172 }
173
174 return tpnf;
175}
176
177
178template<class Type>
181{
184 (
185 this->primitiveField()
186 );
187
188 return refCast<const cyclicAMIFvPatchField<Type>>
189 (
190 fld.boundaryField()[cyclicAMIPatch_.neighbPatchID()]
191 );
192}
193
194
195template<class Type>
197(
198 solveScalarField& result,
199 const bool add,
200 const lduAddressing& lduAddr,
201 const label patchId,
202 const solveScalarField& psiInternal,
203 const scalarField& coeffs,
204 const direction cmpt,
206) const
207{
208 const labelUList& nbrFaceCells =
209 lduAddr.patchAddr(cyclicAMIPatch_.neighbPatchID());
210
211 solveScalarField pnf(psiInternal, nbrFaceCells);
212
213 const labelUList& faceCells = lduAddr.patchAddr(patchId);
214
215 // Transform according to the transformation tensors
216 transformCoupleField(pnf, cmpt);
217
218 if (cyclicAMIPatch_.applyLowWeightCorrection())
219 {
220 solveScalarField pif(psiInternal, faceCells);
221 pnf = cyclicAMIPatch_.interpolate(pnf, pif);
222 }
223 else
224 {
225 pnf = cyclicAMIPatch_.interpolate(pnf);
226 }
227
228 // Multiply the field by coefficients and add into the result
229 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
230}
232
233template<class Type>
235(
236 Field<Type>& result,
237 const bool add,
238 const lduAddressing& lduAddr,
239 const label patchId,
240 const Field<Type>& psiInternal,
241 const scalarField& coeffs,
243) const
244{
245 const labelUList& nbrFaceCells =
246 lduAddr.patchAddr(cyclicAMIPatch_.neighbPatchID());
247
248 Field<Type> pnf(psiInternal, nbrFaceCells);
249
250 // Transform according to the transformation tensors
251 transformCoupleField(pnf);
252
253 if (cyclicAMIPatch_.applyLowWeightCorrection())
254 {
255 Field<Type> pif(psiInternal, cyclicAMIPatch_.faceCells());
256 pnf = cyclicAMIPatch_.interpolate(pnf, pif);
257 }
258 else
259 {
260 pnf = cyclicAMIPatch_.interpolate(pnf);
261 }
262
263 const labelUList& faceCells = lduAddr.patchAddr(patchId);
264
265 // Multiply the field by coefficients and add into the result
266 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
267}
268
269
270template<class Type>
272(
273 fvMatrix<Type>& matrix,
274 const label mat,
275 const direction cmpt
276)
277{
278
279 if (this->cyclicAMIPatch().owner())
280 {
281 label index = this->patch().index();
282
283 const label globalPatchID =
284 matrix.lduMeshAssembly().patchLocalToGlobalMap()[mat][index];
285
286 const Field<scalar> intCoeffsCmpt
287 (
288 matrix.internalCoeffs()[globalPatchID].component(cmpt)
289 );
290
291 const Field<scalar> boundCoeffsCmpt
292 (
293 matrix.boundaryCoeffs()[globalPatchID].component(cmpt)
294 );
295
296 tmp<Field<scalar>> tintCoeffs(coeffs(matrix, intCoeffsCmpt, mat));
297 tmp<Field<scalar>> tbndCoeffs(coeffs(matrix, boundCoeffsCmpt, mat));
298 const Field<scalar>& intCoeffs = tintCoeffs.ref();
299 const Field<scalar>& bndCoeffs = tbndCoeffs.ref();
300
301 const labelUList& u = matrix.lduAddr().upperAddr();
302 const labelUList& l = matrix.lduAddr().lowerAddr();
303
304 label subFaceI = 0;
305
306 const labelList& faceMap =
307 matrix.lduMeshAssembly().faceBoundMap()[mat][index];
308
309 forAll (faceMap, j)
310 {
311 label globalFaceI = faceMap[j];
312
313 const scalar boundCorr = -bndCoeffs[subFaceI];
314 const scalar intCorr = -intCoeffs[subFaceI];
315
316 matrix.upper()[globalFaceI] += boundCorr;
317 matrix.diag()[u[globalFaceI]] -= intCorr;
318 matrix.diag()[l[globalFaceI]] -= boundCorr;
319
320 if (matrix.asymmetric())
321 {
322 matrix.lower()[globalFaceI] += intCorr;
323 }
324 subFaceI++;
325 }
326
327 // Set internalCoeffs and boundaryCoeffs in the assembly matrix
328 // on clyclicAMI patches to be used in the individual matrix by
329 // matrix.flux()
330 if (matrix.psi(mat).mesh().fluxRequired(this->internalField().name()))
331 {
332 matrix.internalCoeffs().set
333 (
334 globalPatchID, intCoeffs*pTraits<Type>::one
335 );
336 matrix.boundaryCoeffs().set
337 (
338 globalPatchID, bndCoeffs*pTraits<Type>::one
339 );
340
341 const label nbrPathID =
342 cyclicAMIPatch_.cyclicAMIPatch().neighbPatchID();
343
344 const label nbrGlobalPatchID =
346 [mat][nbrPathID];
347
348 matrix.internalCoeffs().set
349 (
350 nbrGlobalPatchID, intCoeffs*pTraits<Type>::one
351 );
352 matrix.boundaryCoeffs().set
353 (
354 nbrGlobalPatchID, bndCoeffs*pTraits<Type>::one
355 );
356 }
357 }
358}
359
360
361template<class Type>
364(
365 fvMatrix<Type>& matrix,
366 const Field<scalar>& coeffs,
367 const label mat
368) const
369{
370 const label index(this->patch().index());
371
372 const label nSubFaces
373 (
374 matrix.lduMeshAssembly().cellBoundMap()[mat][index].size()
375 );
376
377 Field<scalar> mapCoeffs(nSubFaces, Zero);
378
379 const scalarListList& srcWeight =
380 cyclicAMIPatch_.cyclicAMIPatch().AMI().srcWeights();
381
382 label subFaceI = 0;
383 forAll(*this, faceI)
384 {
385 const scalarList& w = srcWeight[faceI];
386 for(label i=0; i<w.size(); i++)
387 {
388 const label localFaceId =
389 matrix.lduMeshAssembly().facePatchFaceMap()[mat][index][subFaceI];
390 mapCoeffs[subFaceI] = w[i]*coeffs[localFaceId];
391 subFaceI++;
392 }
393 }
394
395 return tmp<Field<scalar>>(new Field<scalar>(mapCoeffs));
396}
397
398
399template<class Type>
400template<class Type2>
402(
403 const refPtr<mapDistribute>& mapPtr,
404 const labelListList& stencil,
405 const Type2& data,
406 List<Type2>& expandedData
407)
408{
409 expandedData.setSize(stencil.size());
410 if (mapPtr)
411 {
412 Type2 work(data);
413 mapPtr().distribute(work);
414
415 forAll(stencil, facei)
416 {
417 const labelList& slots = stencil[facei];
418 expandedData[facei].append
419 (
420 UIndirectList<typename Type2::value_type>(work, slots)
421 );
422 }
423 }
424 else
425 {
426 forAll(stencil, facei)
427 {
428 const labelList& slots = stencil[facei];
429 expandedData[facei].append
430 (
431 UIndirectList<typename Type2::value_type>(data, slots)
432 );
433 }
434 }
435}
436
437
438template<class Type>
440{
442 this->writeEntry("value", os);
443}
444
445
446// ************************************************************************* //
447
bool found
Info<< nl<< "Wrote faMesh in vtk format: "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.mesh().time().globalPath()/"finiteArea-edges"));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
static const char *const typeName
Typename for Field.
Definition: FieldBase.H:59
Generic templated field type.
Definition: Field.H:82
Generic GeometricField class.
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:65
void setSize(const label n)
Alias for resize()
Definition: List.H:218
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
commsTypes
Types of communications.
Definition: UPstream.H:67
const dictionary & coeffs() const
Return const dictionary of the model.
Abstract base class for coupled patches.
virtual void evaluate(const Pstream::commsTypes commsType)
Evaluate the patch field.
virtual const labelUList & faceCells() const
Return faceCell addressing.
This boundary condition enforces a cyclic condition between a pair of boundaries, whereby communicati...
const cyclicAMIFvPatchField< Type > & neighbourPatchField() const
Return reference to neighbour patchField.
virtual void manipulateMatrix(fvMatrix< Type > &m, const label iMatrix, const direction cmpt)
Manipulate matrix.
virtual void updateInterfaceMatrix(solveScalarField &result, const bool add, const lduAddressing &lduAddr, const label patchId, const solveScalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Update result field based on interface functionality.
virtual bool coupled() const
Return true if coupled. Note that the underlying patch.
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour coupled internal cell data.
Cyclic patch for Arbitrary Mesh Interface (AMI)
virtual const cyclicAMIFvPatch & neighbPatch() const
Return processor number.
Abstract base class for cyclic AMI coupled interfaces.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
Definition: dictionaryI.H:87
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:59
virtual bool write()
Write the output fields.
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvMatrix.H:121
const FieldField< Field, Type > & internalCoeffs() const noexcept
Definition: fvMatrix.H:470
const FieldField< Field, Type > & boundaryCoeffs() const noexcept
Definition: fvMatrix.H:484
const lduPrimitiveMeshAssembly & lduMeshAssembly()
Return optional lduAdressing.
Definition: fvMatrix.H:405
const GeometricField< Type, fvPatchField, volMesh > & psi(const label i=0) const
Return psi.
Definition: fvMatrix.H:412
A FieldMapper for finite-volume patch fields.
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:82
virtual tmp< Field< Type > > patchInternalField() const
Return internal field next to patch as patch field.
Definition: fvPatchField.C:237
virtual void operator=(const UList< Type > &)
Definition: fvPatchField.C:408
const DimensionedField< Type, volMesh > & internalField() const
Return dimensioned internal field reference.
Definition: fvPatchField.H:368
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:362
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:71
virtual const word & name() const
Return name.
Definition: fvPatch.H:173
The class contains the addressing required by the lduMatrix: upper, lower and losort.
virtual const labelUList & upperAddr() const =0
Return upper addressing.
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
scalarField & upper()
Definition: lduMatrix.C:203
const lduAddressing & lduAddr() const
Return the LDU addressing.
Definition: lduMatrix.H:578
scalarField & lower()
Definition: lduMatrix.C:174
scalarField & diag()
Definition: lduMatrix.C:192
bool asymmetric() const
Definition: lduMatrix.H:633
const labelListListList & cellBoundMap() const
Return patch local sub-face to nbrCellId map.
const labelListListList & faceBoundMap() const
Return boundary face map.
const labelListListList & facePatchFaceMap() const
Return patch local sub-face to local patch face map.
const labelListList & patchLocalToGlobalMap() const
Return patchLocalToGlobalMap.
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition: one.H:62
A class for managing temporary objects.
Definition: tmp.H:65
T & ref() const
Definition: tmpI.H:227
volScalarField & p
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
OBJstream os(runTime.globalPath()/outputName)
label patchId(-1)
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
To & refCast(From &r)
Reference type cast template function.
Definition: typeInfo.H:131
List< label > labelList
A List of labels.
Definition: List.H:66
uint8_t direction
Definition: direction.H:56
IOerror FatalIOError
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
dict add("bounds", meshBb)
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333