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 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 
29 #include "fvMatrix.H"
30 #include "volFields.H"
31 //#include "cylicFvPatchField.H"
32 
33 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
34 
35 template<class Type>
37 (
38  const fvPatch& p,
40 )
41 :
44  cyclicAMIPatch_(refCast<const cyclicAMIFvPatch>(p))
45 {}
46 
47 
48 template<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()
68  << exit(FatalIOError);
69  }
70 
71  if (!dict.found("value"))
72  {
73  if (this->coupled())
74  {
75  this->evaluate(Pstream::commsTypes::blocking);
76  }
77  else
78  {
79  fvPatchField<Type>::operator=(this->patchInternalField());
80  }
81  }
82 }
83 
84 
85 template<class Type>
87 (
88  const cyclicAMIFvPatchField<Type>& ptf,
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 
110 template<class Type>
112 (
113  const cyclicAMIFvPatchField<Type>& ptf
114 )
115 :
118  cyclicAMIPatch_(ptf.cyclicAMIPatch_)
119 {}
120 
121 
122 template<class Type>
124 (
125  const cyclicAMIFvPatchField<Type>& ptf,
127 )
128 :
130  coupledFvPatchField<Type>(ptf, iF),
131  cyclicAMIPatch_(ptf.cyclicAMIPatch_)
132 {}
133 
134 
135 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
136 
137 template<class Type>
139 {
140  return cyclicAMIPatch_.coupled();
141 }
142 
143 
144 template<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 
178 template<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 
195 template<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,
205  const Pstream::commsTypes
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 }
231 
232 
233 template<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,
242  const Pstream::commsTypes
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 
270 template<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 =
345  matrix.lduMeshAssembly().patchLocalToGlobalMap()
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 
361 template<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 
399 template<class Type>
400 template<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.valid())
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 
438 template<class Type>
440 {
442  this->writeEntry("value", os);
443 }
444 
445 
446 // ************************************************************************* //
447 
Foam::fvPatchField
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: volSurfaceMapping.H:51
Foam::lduAddressing
The class contains the addressing required by the lduMatrix: upper, lower and losort.
Definition: lduAddressing.H:114
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
volFields.H
Foam::fvMatrix::lduMeshAssembly
const lduPrimitiveMeshAssembly & lduMeshAssembly()
Return optional lduAdressing.
Definition: fvMatrix.H:392
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::cyclicAMILduInterfaceField
Abstract base class for cyclic AMI coupled interfaces.
Definition: cyclicAMILduInterfaceField.H:51
Foam::cyclicAMIFvPatchField::write
virtual void write(Ostream &os) const
Write.
Definition: cyclicAMIFvPatchField.C:439
Foam::cyclicAMIFvPatch::neighbPatch
virtual const cyclicAMIFvPatch & neighbPatch() const
Return processor number.
Definition: cyclicAMIFvPatch.H:158
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
Foam::FatalIOError
IOerror FatalIOError
Foam::fvMatrix::boundaryCoeffs
const FieldField< Field, Type > & boundaryCoeffs() const
Definition: fvMatrix.H:471
fvMatrix.H
Foam::transform
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:521
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::cyclicAMIFvPatchField
This boundary condition enforces a cyclic condition between a pair of boundaries, whereby communicati...
Definition: cyclicAMIFvPatchField.H:77
Foam::cyclicAMIFvPatchField::manipulateMatrix
virtual void manipulateMatrix(fvMatrix< Type > &m, const label iMatrix, const direction cmpt)
Manipulate matrix.
Definition: cyclicAMIFvPatchField.C:272
Foam::tmp::ref
T & ref() const
Definition: tmpI.H:227
Foam::Field
Generic templated field type.
Definition: Field.H:63
Foam::fvPatch
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:65
fld
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputLagrangian.H:23
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::fvMatrix::psi
const GeometricField< Type, fvPatchField, volMesh > & psi(const label i=0) const
Return psi.
Definition: fvMatrix.H:399
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::add
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
Definition: FieldFieldFunctions.C:939
os
OBJstream os(runTime.globalPath()/outputName)
Foam::cyclicAMIFvPatchField::updateInterfaceMatrix
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.
Definition: cyclicAMIFvPatchField.C:197
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::coupledFvPatch::faceCells
virtual const labelUList & faceCells() const
Return faceCell addressing.
Definition: coupledFvPatch.H:114
Foam::UPstream::commsTypes
commsTypes
Types of communications.
Definition: UPstream.H:69
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::cyclicAMIFvPatchField::cyclicAMIFvPatchField
cyclicAMIFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
Definition: cyclicAMIFvPatchField.C:37
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::coupledFvPatchField
Abstract base class for coupled patches.
Definition: coupledFvPatchField.H:57
Foam::List< label >
Foam::pTraits
A traits class, which is primarily used for primitives.
Definition: pTraits.H:56
Foam::UList< label >
Foam::cyclicAMIFvPatchField::coupled
virtual bool coupled() const
Return true if coupled. Note that the underlying patch.
Definition: cyclicAMIFvPatchField.C:138
Foam::direction
uint8_t direction
Definition: direction.H:52
Foam::fvMatrix
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvPatchField.H:68
Foam::vtk::write
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
Definition: foamVtkOutputTemplates.C:36
Foam::lduAddressing::patchAddr
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::cyclicAMIFvPatch
Cyclic patch for Arbitrary Mesh Interface (AMI)
Definition: cyclicAMIFvPatch.H:54
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
Foam::fvPatchFieldMapper
Foam::fvPatchFieldMapper.
Definition: fvPatchFieldMapper.H:47
patchId
label patchId(-1)
Foam::cyclicAMIFvPatchField::patchNeighbourField
virtual tmp< Field< Type > > patchNeighbourField() const
Return neighbour coupled internal cell data.
Definition: cyclicAMIFvPatchField.C:146
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
coupled
bool coupled(solutionDict.getOrDefault("coupledEnergyField", false))
Foam::fvMatrix::internalCoeffs
const FieldField< Field, Type > & internalCoeffs() const
Definition: fvMatrix.H:457
Foam::GeometricField< Type, fvPatchField, volMesh >
Foam::faceCells
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:56
Foam::DimensionedField
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: DimensionedField.H:54
Foam::cyclicAMIFvPatchField::neighbourPatchField
const cyclicAMIFvPatchField< Type > & neighbourPatchField() const
Return reference to neighbour patchField.
Definition: cyclicAMIFvPatchField.C:180
Foam::stringOps::evaluate
string evaluate(label fieldWidth, const std::string &s, size_t pos=0, size_t len=std::string::npos)
String evaluation with specified (positive, non-zero) field width.
Definition: stringOpsEvaluate.C:37