Go to the documentation of this file.
42 "immersedBoundaryNBCIter",
48 const Foam::debug::tolerancesSwitch
51 "immersedBoundaryBCTolerance",
68 if (this->fixesValue())
70 ibValue_ = ibPatch_.toIbPoints(refValue_);
71 ibGrad_ = (ibValue_ - ibcv)/ibPatch_.ibDelta();
74 if (!ibPatch_.internalFlow())
81 ibGrad_ = ibPatch_.toIbPoints(refGrad_);
83 ibValue_ = ibcv + ibGrad_*ibPatch_.ibDelta();
93 const labelList& ibc = ibPatch_.ibCells();
97 ibPatch_.invDirichletMatrices();
107 ibValue_ = ibPatch_.toIbPoints(refValue_);
110 ibGrad_.setSize(ibc.
size());
124 if (mesh_.nGeometricD() == 3)
146 scalar maxMagPolyPsi = 0;
150 label curCell = ibc[cellI];
152 const labelList& curCells = ibCellCells[cellI];
161 curCells.
size() + curProcCells.
size(),
166 for (
label i = 0; i < curCells.
size(); i++)
168 source[pointID++] = psiI[curCells[i]] - ibValue_[cellI];
171 for (
label i = 0; i < curProcCells.
size(); i++)
176 curProcCells[i].first()
179 curProcCells[i].second()
184 for (
label i = 0; i < nCoeffs; i++)
186 for (
label j = 0; j < source.size(); j++)
188 coeffs[i] += curInvMatrix[i][j]*source[j];
192 Type oldPolyPsi = polyPsi[cellI];
200 + coeffs[2]*
R.x()*
R.y()
201 + coeffs[3]*
sqr(
R.x())
202 + coeffs[4]*
sqr(
R.y());
204 if (mesh_.nGeometricD() == 3)
208 + coeffs[6]*
R.x()*
R.z()
209 + coeffs[7]*
R.y()*
R.z()
210 + coeffs[8]*
sqr(
R.z());
215 -coeffs[0]*ibn[cellI].x()
216 - coeffs[1]*ibn[cellI].y();
218 if (mesh_.nGeometricD() == 3)
222 -coeffs[5]*ibn[cellI].z();
225 error[cellI] =
mag(polyPsi[cellI] - oldPolyPsi);
229 setIbCellValues(polyPsi);
234 if (!polyPsi.empty())
236 maxMagPolyPsi =
max(
mag(polyPsi));
246 error /= maxMagPolyPsi + SMALL;
249 if (!polyPsi.empty())
261 while (maxError > bcTolerance_ && counter < nBcIter_);
263 if (counter == nBcIter_() && debug)
267 "template<class Type>\n"
268 "tmp<Foam::Field<Type> >\n"
269 "immersedBoundaryFvPatchField<Type>::"
270 "imposeDirichletCondition() const"
272 <<
" for patch " << this->patch().name()
287 const labelList& ibc = ibPatch_.ibCells();
294 ibPatch_.invNeumannMatrices();
299 ibGrad_ = ibPatch_.toIbPoints(refGrad_);
302 ibValue_.setSize(ibc.
size());
316 if (mesh_.nGeometricD() == 3)
326 setIbCellValues(ibSamplingPointValue());
342 scalar maxMagPolyPsi = 0;
346 label curCell = ibc[cellI];
348 const labelList& curCells = ibCellCells[cellI];
356 curCells.
size() + 1 + curProcCells.
size(),
361 for (
label i = 0; i < curCells.
size(); i++)
363 source[pointID++] = psiI[curCells[i]];
366 source[pointID++] = ibGrad_[cellI];
368 for (
label i = 0; i < curProcCells.
size(); i++)
373 curProcCells[i].first()
376 curProcCells[i].second()
380 for (
label i = 0; i < nCoeffs; i++)
382 for (
label j = 0; j < source.size(); j++)
384 coeffs[i] += curInvMatrix[i][j]*source[j];
388 Type oldPolyPsi = polyPsi[cellI];
390 vector ibR =
C[curCell] - ibp[cellI];
396 + coeffs[3]*ibR.
x()*ibR.
y()
397 + coeffs[4]*
sqr(ibR.
x())
398 + coeffs[5]*
sqr(ibR.
y());
400 if (mesh_.nGeometricD() == 3)
404 + coeffs[7]*ibR.
x()*ibR.
z()
405 + coeffs[8]*ibR.
y()*ibR.
z()
406 + coeffs[9]*
sqr(ibR.
z());
409 ibValue_[cellI] = coeffs[0];
411 error[cellI] =
mag(polyPsi[cellI] - oldPolyPsi);
415 setIbCellValues(polyPsi);
420 if (!polyPsi.empty())
422 maxMagPolyPsi =
max(
mag(polyPsi));
432 error /= maxMagPolyPsi + SMALL;
435 if (!polyPsi.empty())
447 while (maxError > bcTolerance_() && counter < nBcIter_());
449 if (counter == nBcIter_() && debug)
453 "template<class Type>\n"
454 "tmp<Foam::Field<Type> >\n"
455 "immersedBoundaryFvPatchField<Type>::"
456 "imposeNeumannCondition() const"
458 <<
" for patch " << this->patch().name()
476 const labelList& dc = ibPatch_.deadCells();
488 psiI[dc[dcI]] = deadCellValue_;
501 const labelList& dce = ibPatch_.deadCellsExt();
506 if (dce.
size() < Diag.size())
508 liveDiag =
gSumMag(Diag)/(Diag.size() - dce.
size());
516 if (
mag(Diag[dce[cellI]]) < SMALL)
518 Diag[dce[cellI]] = liveDiag;
531 const labelList& ibFaces = ibPatch_.ibFaces();
532 const labelList& ibFaceCells = ibPatch_.ibFaceCells();
534 const scalarField& ibGamma = ibPatch_.gamma().internalField();
554 const label curFace = ibFaces[faceI];
556 if (curFace < nei.
size())
561 if (ibGamma[own[curFace]] > SMALL)
563 diag[own[curFace]] += upper[curFace];
565 source[own[curFace]] +=
566 upper[curFace]*ibGrad_[ibFaceCells[faceI]]
571 diag[nei[curFace]] += upper[curFace];
573 source[nei[curFace]] -=
574 upper[curFace]*ibGrad_[ibFaceCells[faceI]]
583 label patchi = mesh_.boundaryMesh().whichPatch(curFace);
588 mesh_.boundaryMesh()[
patchi].whichFace(curFace);
598 if (ibFaceCells[faceI] > -1)
600 if (ibGamma[ibFaceCells[faceI]] > SMALL)
602 source[ibFaceCells[faceI]] +=
603 ibGrad_[ibFaceCells[faceI]]
611 else if (eqn.asymmetric())
623 const label curFace = ibFaces[faceI];
625 if (curFace < nei.
size())
630 if (ibGamma[own[curFace]] > SMALL)
632 diag[own[curFace]] += upper[curFace];
634 source[own[curFace]] +=
635 upper[curFace]*ibGrad_[ibFaceCells[faceI]]/dcI[faceI];
639 diag[nei[curFace]] += lower[curFace];
641 source[nei[curFace]] -=
642 lower[curFace]*ibGrad_[ibFaceCells[faceI]]/dcI[faceI];
651 label patchi = mesh_.boundaryMesh().whichPatch(curFace);
656 mesh_.boundaryMesh()[
patchi].whichFace(curFace);
666 if (ibFaceCells[faceI] > -1)
668 if (ibGamma[ibFaceCells[faceI]] > SMALL)
670 source[ibFaceCells[faceI]] +=
671 ibGrad_[ibFaceCells[faceI]]
693 || ibPatch_.boundaryMesh().mesh().moving()
699 != ibPatch_.boundaryMesh().mesh().time().timeIndex()
719 ibUpdateTimeIndex_ = ibPatch_.boundaryMesh().mesh().time().timeIndex();
729 const labelList& ibc = ibPatch_.ibCells();
731 if (ibcValues.size() != ibc.
size())
735 "template<class Type>\n"
736 "void immersedBoundaryFvPatchField<Type>::setIbCellValues\n"
738 " const Field<Type>& ibcValues\n"
740 ) <<
"Size of ibcValues field not equal to the number of IB cells."
741 <<
nl <<
"ibcValues: " << ibcValues.size()
742 <<
" ibc: " << ibc.
size()
751 psiI[ibc[cellI]] = ibcValues[cellI];
766 ibPatch_(refCast<const immersedBoundaryFvPatch>(
p)),
767 mesh_(
p.boundaryMesh().mesh()),
771 setDeadCellValue_(
false),
787 ibPatch_(refCast<const immersedBoundaryFvPatch>(
p)),
788 mesh_(
p.boundaryMesh().mesh()),
789 refValue_(
"refValue",
dict, ibPatch_.ibMesh().size()),
790 refGrad_(
"refGradient",
dict, ibPatch_.ibMesh().size()),
792 setDeadCellValue_(
dict.
lookup(
"setDeadCellValue")),
797 if (!isType<immersedBoundaryFvPatch>(
p))
801 "immersedBoundaryFvPatchField<Type>::"
802 "immersedBoundaryFvPatchField\n"
804 " const fvPatch& p,\n"
805 " const Field<Type>& field,\n"
806 " const dictionary& dict\n"
809 ) <<
"\n patch type '" <<
p.type()
810 <<
"' not constraint type '" << typeName <<
"'"
811 <<
"\n for patch " <<
p.name()
829 ibPatch_(refCast<const immersedBoundaryFvPatch>(
p)),
830 mesh_(
p.boundaryMesh().mesh()),
841 if (!isType<immersedBoundaryFvPatch>(
p))
845 "immersedBoundaryFvPatchField<Type>::"
846 "immersedBoundaryFvPatchField\n"
848 " const immersedBoundaryFvPatchField<Type>&,\n"
849 " const fvPatch& p,\n"
850 " const DimensionedField<Type, volMesh>& iF,\n"
851 " const fvPatchFieldMapper& mapper\n"
853 ) <<
"\n patch type '" <<
p.type()
854 <<
"' not constraint type '" << typeName <<
"'"
855 <<
"\n for patch " <<
p.name()
910 if (this->motionUpdateRequired())
915 if (ibValue_.empty())
917 this->updateIbValues();
930 if (this->motionUpdateRequired())
937 this->updateIbValues();
972 return ibPatch_.toTriFaces(this->ibValue());
979 return ibPatch_.toTriFaces(this->ibGrad());
986 if (this->fixesValue())
988 this->imposeDirichletCondition();
992 this->imposeNeumannCondition();
996 if (setDeadCellValue_)
998 this->imposeDeadCondition();
1005 template<
class Type>
1011 this->updateCoeffs();
1015 template<
class Type>
1032 template<
class Type>
1038 this->initEvaluate();
1041 this->correctDiag(eqn);
1044 if (!this->fixesValue())
1046 this->correctOffDiag(eqn);
1051 eqn.
setValues(ibPatch_.ibCells(), polyPsi);
1056 ibPatch_.deadCells().size(),
1059 eqn.
setValues(ibPatch_.deadCells(), deadCellsPsi);
1065 template<
class Type>
1069 refValue_.writeEntry(
"refValue", os);
1070 refGrad_.writeEntry(
"refGradient", os);
1077 this->writeEntry(
"value", os);
1089 f[faceI] = ts[faceI].triFaceFace();
1098 this->dimensionedInternalField().name(),
virtual void write(Ostream &) const
Write.
virtual void manipulateMatrix(fvMatrix< Type > &matrix)
Manipulate matrix.
virtual void evaluate(const Pstream::commsTypes commsType=Pstream::blocking)
Evaluate the patch field, sets Updated to false.
#define InfoIn(functionName)
Report a information message using Foam::Info.
const Field< PointType > & points() const
Return reference to global points.
#define forAll(list, i)
Loop across all elements in list.
A class for managing temporary objects.
Type gAverage(const FieldField< Field, Type > &f)
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
virtual void evaluate(const Pstream::commsTypes commsType=Pstream::blocking)
Evaluate the patch field.
rDeltaT dimensionedInternalField()
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
virtual void initEvaluate(const Pstream::commsTypes commsType=Pstream::blocking)
Initialise the evaluation of the patch field.
virtual Field< Type > & refGrad()
Return access to reference gradient.
GeometricBoundaryField & boundaryField()
Return reference to GeometricBoundaryField.
FieldField< Field, Type > & internalCoeffs()
fvBoundary scalar field containing pseudo-matrix coeffs
Ostream & endl(Ostream &os)
Add newline and flush stream.
const Field< Type > & ibValue() const
Return fields on intersection points interacting with the IB.
dimensioned< scalar > mag(const dimensioned< Type > &)
const fvMesh & mesh() const
Return the mesh reference.
dimensionedScalar sign(const dimensionedScalar &ds)
const GeometricField< Type, fvPatchField, volMesh > & psi() const
word name() const
Return file name (part beyond last /)
const fvBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
bool motionUpdateRequired() const
Does immersed boundary patch field need motion update?
immersedBoundaryFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
virtual Field< Type > & refValue()
Return access to reference value.
void imposeDeadCondition()
Impose condition in dead cells.
void updateCoeffs()
Update the coefficients associated with the patch field.
void updateIbValues() const
Update IB value and gradient.
int optimisationSwitch(const char *name, const int defaultValue=0)
Lookup optimisation switch or add default value.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
void setValues(const labelUList &cells, const UList< Type > &values)
Set solution in given cells to the specified values.
#define R(A, B, C, D, E, F, K, M)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Triangulated surface description with patch information.
const immersedBoundaryFvPatch & ibPatch() const
Return reference to immersed boundary patch.
const Field< Type > & ibGrad() const
Return IB surface-normal gradient.
virtual bool fixesValue() const
Return true if this patch field fixes a value.
void correctOffDiag(fvMatrix< Type > &eqn) const
Impose fixed gradient condition by manipulating matrix.
tmp< Field< Type > > imposeDirichletCondition() const
Impose Dirichlet BC at IB cells and return corrected cells values.
tmp< Field< Type > > ibCellValue() const
Return IB cell field.
Type deadCellValue_
Dead cell value.
tmp< Field< Type > > ibSamplingPointValue() const
Return IB sample point field.
virtual void write(Ostream &) const
Write.
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
#define FatalIOErrorIn(functionName, ios)
Report an error message using Foam::FatalIOError.
InternalField & internalField()
Return internal field.
tmp< Field< Type > > triGrad() const
Return IB surface-normal gradient.
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
A list of keyword definitions, which are a keyword followed by any number of values (e....
static const debug::tolerancesSwitch bcTolerance_
Boundary condition update tolerance.
errorManip< error > abort(error &err)
virtual void manipulateMatrix(fvMatrix< Type > &matrix)
Manipulate matrix.
scalar gSumMag(const FieldField< Field, Type > &f)
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
errorManipArg< error, int > exit(error &err, const int errNo=1)
FieldField< Field, Type > & boundaryCoeffs()
fvBoundary scalar field containing pseudo-matrix coeffs
Switch setDeadCellValue_
Set dead cell value.
conserve internalField()+
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
static const debug::optimisationSwitch nBcIter_
Number of boundary condition update iterations.
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
void correctDiag(fvMatrix< Type > &eqn) const
Check and correct zero diagonal in dead cells.
commsTypes
Types of communications.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
static autoPtr< surfaceWriter > New(const word &writeType)
Return a reference to the selected surfaceWriter.
virtual void setIbCellValues(const Field< Type > &) const
Set IB cell values.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Traits class for primitives.
Ostream & writeKeyword(const keyType &)
Write the keyword followed by an appropriate indentation.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Foam::immersedBoundaryFvPatchField.
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
tmp< Field< Type > > imposeNeumannCondition() const
Impose Neumann BC at IB cells and return corrected cells values.
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Foam::fvPatchFieldMapper.
const fvPatch & patch() const
Return patch.
tmp< Field< Type > > triValue() const
Return fields on triangular faces.
void size(const label)
Override size to be inconsistent with allocated storage.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Type gMin(const FieldField< Field, Type > &f)
label size() const
Return the number of elements in the UList.
Graphite solid properties.
Generic GeometricField class.
virtual void motionUpdate() const
Execute immersed boundary patch field motion update.
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Type gMax(const FieldField< Field, Type > &f)
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...