BUG: cyclicACMI: make conservative. Remove faceAreas0
This commit is contained in:
parent
5d29b49811
commit
c4b5880f9c
@ -175,9 +175,6 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
Info<< "Time = " << runTime.timeName() << nl << endl;
|
||||
|
||||
// Clear mesh before checking
|
||||
mesh.clearOut();
|
||||
|
||||
// Reconstruct globalMeshData
|
||||
mesh.globalData();
|
||||
|
||||
|
@ -137,22 +137,15 @@ Foam::tmp<Foam::Field<Type>>
|
||||
Foam::cyclicACMIFvPatchField<Type>::patchNeighbourField() const
|
||||
{
|
||||
const Field<Type>& iField = this->internalField();
|
||||
const labelUList& nbrFaceCellsCoupled =
|
||||
cyclicACMIPatch_.cyclicACMIPatch().neighbPatch().faceCells();
|
||||
const labelUList& faceCellsNonOverlap =
|
||||
cyclicACMIPatch_.cyclicACMIPatch().nonOverlapPatch().faceCells();
|
||||
|
||||
Field<Type> pnfCoupled(iField, nbrFaceCellsCoupled);
|
||||
Field<Type> pfNonOverlap(iField, faceCellsNonOverlap);
|
||||
|
||||
const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch();
|
||||
tmp<Field<Type>> tpnf
|
||||
(
|
||||
new Field<Type>
|
||||
cyclicACMIPatch_.interpolate
|
||||
(
|
||||
cyclicACMIPatch_.interpolate
|
||||
Field<Type>
|
||||
(
|
||||
pnfCoupled,
|
||||
pfNonOverlap
|
||||
iField,
|
||||
cpp.neighbPatch().faceCells()
|
||||
)
|
||||
)
|
||||
);
|
||||
@ -207,10 +200,12 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
|
||||
const Pstream::commsTypes
|
||||
) const
|
||||
{
|
||||
const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch();
|
||||
|
||||
// note: only applying coupled contribution
|
||||
|
||||
const labelUList& nbrFaceCellsCoupled =
|
||||
cyclicACMIPatch_.cyclicACMIPatch().neighbPatch().faceCells();
|
||||
cpp.neighbPatch().faceCells();
|
||||
|
||||
scalarField pnf(psiInternal, nbrFaceCellsCoupled);
|
||||
|
||||
@ -237,10 +232,11 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
|
||||
const Pstream::commsTypes
|
||||
) const
|
||||
{
|
||||
const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch();
|
||||
|
||||
// note: only applying coupled contribution
|
||||
|
||||
const labelUList& nbrFaceCellsCoupled =
|
||||
cyclicACMIPatch_.cyclicACMIPatch().neighbPatch().faceCells();
|
||||
const labelUList& nbrFaceCellsCoupled = cpp.neighbPatch().faceCells();
|
||||
|
||||
Field<Type> pnf(psiInternal, nbrFaceCellsCoupled);
|
||||
|
||||
@ -258,149 +254,6 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>> Foam::cyclicACMIFvPatchField<Type>::snGrad
|
||||
(
|
||||
const scalarField& deltaCoeffs
|
||||
) const
|
||||
{
|
||||
// note: only applying coupled contribution
|
||||
return coupledFvPatchField<Type>::snGrad(deltaCoeffs);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::cyclicACMIFvPatchField<Type>::updateCoeffs()
|
||||
{
|
||||
// update non-overlap patch - some will implement updateCoeffs, and
|
||||
// others will implement evaluate
|
||||
|
||||
// scale neighbour field by (1 - mask)
|
||||
|
||||
const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
|
||||
const fvPatchField<Type>& npf = nonOverlapPatchField();
|
||||
const_cast<fvPatchField<Type>&>(npf).updateCoeffs(1.0 - mask);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::cyclicACMIFvPatchField<Type>::initEvaluate
|
||||
(
|
||||
const Pstream::commsTypes comms
|
||||
)
|
||||
{
|
||||
// update non-overlap patch (if not already updated by updateCoeffs)
|
||||
|
||||
// scale neighbour field by (1 - mask)
|
||||
|
||||
fvPatchField<Type>& npf =
|
||||
const_cast<fvPatchField<Type>&>(nonOverlapPatchField());
|
||||
|
||||
if (!npf.updated())
|
||||
{
|
||||
const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
|
||||
|
||||
npf.evaluate(comms);
|
||||
|
||||
npf *= 1.0 - mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::cyclicACMIFvPatchField<Type>::evaluate
|
||||
(
|
||||
const Pstream::commsTypes comms
|
||||
)
|
||||
{
|
||||
// blend contributions from the coupled and non-overlap patches
|
||||
|
||||
// neighbour patch field is updated via updateCoeffs or initEvaluate
|
||||
// and is already scaled by (1 - mask)
|
||||
const fvPatchField<Type>& npf = nonOverlapPatchField();
|
||||
|
||||
coupledFvPatchField<Type>::evaluate(comms);
|
||||
const Field<Type>& cpf = *this;
|
||||
|
||||
const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
|
||||
Field<Type>::operator=(mask*cpf + npf);
|
||||
|
||||
fvPatchField<Type>::evaluate();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::cyclicACMIFvPatchField<Type>::valueInternalCoeffs
|
||||
(
|
||||
const tmp<scalarField>& w
|
||||
) const
|
||||
{
|
||||
// note: do not blend based on mask field
|
||||
// - when applied this is scaled by the areas which are already scaled
|
||||
return coupledFvPatchField<Type>::valueInternalCoeffs(w);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::cyclicACMIFvPatchField<Type>::valueBoundaryCoeffs
|
||||
(
|
||||
const tmp<scalarField>& w
|
||||
) const
|
||||
{
|
||||
// note: do not blend based on mask field
|
||||
// - when applied this is scaled by the areas which are already scaled
|
||||
return coupledFvPatchField<Type>::valueBoundaryCoeffs(w);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::cyclicACMIFvPatchField<Type>::gradientInternalCoeffs
|
||||
(
|
||||
const scalarField& deltaCoeffs
|
||||
) const
|
||||
{
|
||||
// note: do not blend based on mask field
|
||||
// - when applied this is scaled by the areas which are already scaled
|
||||
return coupledFvPatchField<Type>::gradientInternalCoeffs(deltaCoeffs);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::cyclicACMIFvPatchField<Type>::gradientInternalCoeffs() const
|
||||
{
|
||||
// note: do not blend based on mask field
|
||||
// - when applied this is scaled by the areas which are already scaled
|
||||
return coupledFvPatchField<Type>::gradientInternalCoeffs();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::cyclicACMIFvPatchField<Type>::gradientBoundaryCoeffs
|
||||
(
|
||||
const scalarField& deltaCoeffs
|
||||
) const
|
||||
{
|
||||
// note: do not blend based on mask field
|
||||
// - when applied this is scaled by the areas which are already scaled
|
||||
return coupledFvPatchField<Type>::gradientBoundaryCoeffs(deltaCoeffs);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>>
|
||||
Foam::cyclicACMIFvPatchField<Type>::gradientBoundaryCoeffs() const
|
||||
{
|
||||
// note: do not blend based on mask field
|
||||
// - when applied this is scaled by the areas which are already scaled
|
||||
return coupledFvPatchField<Type>::gradientBoundaryCoeffs();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::cyclicACMIFvPatchField<Type>::manipulateMatrix
|
||||
(
|
||||
|
@ -218,63 +218,6 @@ public:
|
||||
const Pstream::commsTypes commsType
|
||||
) const;
|
||||
|
||||
//- Return patch-normal gradient
|
||||
virtual tmp<Field<Type>> snGrad
|
||||
(
|
||||
const scalarField& deltaCoeffs
|
||||
) const;
|
||||
|
||||
//- Update the coefficients associated with the patch field
|
||||
void updateCoeffs();
|
||||
|
||||
//- Initialise the evaluation of the patch field
|
||||
virtual void initEvaluate
|
||||
(
|
||||
const Pstream::commsTypes commsType
|
||||
);
|
||||
|
||||
//- Evaluate the patch field
|
||||
virtual void evaluate
|
||||
(
|
||||
const Pstream::commsTypes commsType
|
||||
);
|
||||
|
||||
//- Return the matrix diagonal coefficients corresponding to the
|
||||
// evaluation of the value of this patchField with given weights
|
||||
virtual tmp<Field<Type>> valueInternalCoeffs
|
||||
(
|
||||
const tmp<scalarField>&
|
||||
) const;
|
||||
|
||||
//- Return the matrix source coefficients corresponding to the
|
||||
// evaluation of the value of this patchField with given weights
|
||||
virtual tmp<Field<Type>> valueBoundaryCoeffs
|
||||
(
|
||||
const tmp<scalarField>&
|
||||
) const;
|
||||
|
||||
//- Return the matrix diagonal coefficients corresponding to the
|
||||
// evaluation of the gradient of this patchField
|
||||
virtual tmp<Field<Type>> gradientInternalCoeffs
|
||||
(
|
||||
const scalarField& deltaCoeffs
|
||||
) const;
|
||||
|
||||
//- Return the matrix diagonal coefficients corresponding to the
|
||||
// evaluation of the gradient of this patchField
|
||||
virtual tmp<Field<Type>> gradientInternalCoeffs() const;
|
||||
|
||||
//- Return the matrix source coefficients corresponding to the
|
||||
// evaluation of the gradient of this patchField
|
||||
virtual tmp<Field<Type>> gradientBoundaryCoeffs
|
||||
(
|
||||
const scalarField& deltaCoeffs
|
||||
) const;
|
||||
|
||||
//- Return the matrix source coefficients corresponding to the
|
||||
// evaluation of the gradient of this patchField
|
||||
virtual tmp<Field<Type>> gradientBoundaryCoeffs() const;
|
||||
|
||||
//- Manipulate matrix
|
||||
virtual void manipulateMatrix(fvMatrix<Type>& matrix);
|
||||
|
||||
|
@ -43,7 +43,12 @@ void Foam::cyclicACMIFvPatch::updateAreas() const
|
||||
{
|
||||
if (cyclicACMIPolyPatch_.updated())
|
||||
{
|
||||
// Set Sf and magSf for both sides' coupled and non-overlapping patches
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "cyclicACMIFvPatch::updateAreas() : updating fv areas for "
|
||||
<< name() << " and " << this->nonOverlapPatch().name()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// owner couple
|
||||
const_cast<vectorField&>(Sf()) = patch().faceAreas();
|
||||
@ -81,25 +86,37 @@ void Foam::cyclicACMIFvPatch::makeWeights(scalarField& w) const
|
||||
if (coupled())
|
||||
{
|
||||
const cyclicACMIFvPatch& nbrPatch = neighbFvPatch();
|
||||
const fvPatch& nbrPatchNonOverlap = nonOverlapPatch();
|
||||
|
||||
const scalarField deltas(nf() & coupledFvPatch::delta());
|
||||
|
||||
const scalarField nbrDeltas
|
||||
// These deltas are of the cyclic part alone - they are
|
||||
// not affected by the amount of overlap with the nonOverlapPatch
|
||||
scalarField nbrDeltas
|
||||
(
|
||||
interpolate
|
||||
(
|
||||
nbrPatch.nf() & nbrPatch.coupledFvPatch::delta(),
|
||||
nbrPatchNonOverlap.nf() & nbrPatchNonOverlap.delta()
|
||||
nbrPatch.nf() & nbrPatch.coupledFvPatch::delta()
|
||||
)
|
||||
);
|
||||
|
||||
forAll(deltas, faceI)
|
||||
{
|
||||
scalar di = deltas[faceI];
|
||||
scalar dni = nbrDeltas[faceI];
|
||||
scalar tol = cyclicACMIPolyPatch::tolerance();
|
||||
|
||||
w[faceI] = dni/(di + dni);
|
||||
|
||||
forAll(deltas, facei)
|
||||
{
|
||||
scalar di = deltas[facei];
|
||||
scalar dni = nbrDeltas[facei];
|
||||
|
||||
if (dni < tol)
|
||||
{
|
||||
// Avoid zero weights on disconnected faces. This value
|
||||
// will be weighted with the (zero) face area so will not
|
||||
// influence calculations.
|
||||
w[facei] = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
w[facei] = dni/(di + dni);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -122,30 +139,12 @@ Foam::tmp<Foam::vectorField> Foam::cyclicACMIFvPatch::delta() const
|
||||
{
|
||||
if (coupled())
|
||||
{
|
||||
const cyclicACMIFvPatch& nbrPatchCoupled = neighbFvPatch();
|
||||
const fvPatch& nbrPatchNonOverlap = nonOverlapPatch();
|
||||
const cyclicACMIFvPatch& nbrPatch = neighbFvPatch();
|
||||
|
||||
const vectorField patchD(coupledFvPatch::delta());
|
||||
|
||||
vectorField nbrPatchD
|
||||
(
|
||||
interpolate
|
||||
(
|
||||
nbrPatchCoupled.coupledFvPatch::delta(),
|
||||
nbrPatchNonOverlap.delta()
|
||||
)
|
||||
);
|
||||
vectorField nbrPatchD(interpolate(nbrPatch.coupledFvPatch::delta()));
|
||||
|
||||
const vectorField nbrPatchD0
|
||||
(
|
||||
interpolate
|
||||
(
|
||||
vectorField(nbrPatchCoupled.size(), Zero),
|
||||
nbrPatchNonOverlap.delta()()
|
||||
)
|
||||
);
|
||||
|
||||
nbrPatchD -= nbrPatchD0;
|
||||
|
||||
tmp<vectorField> tpdv(new vectorField(patchD.size()));
|
||||
vectorField& pdv = tpdv.ref();
|
||||
@ -153,22 +152,22 @@ Foam::tmp<Foam::vectorField> Foam::cyclicACMIFvPatch::delta() const
|
||||
// do the transformation if necessary
|
||||
if (parallel())
|
||||
{
|
||||
forAll(patchD, faceI)
|
||||
forAll(patchD, facei)
|
||||
{
|
||||
const vector& ddi = patchD[faceI];
|
||||
const vector& dni = nbrPatchD[faceI];
|
||||
const vector& ddi = patchD[facei];
|
||||
const vector& dni = nbrPatchD[facei];
|
||||
|
||||
pdv[faceI] = ddi - dni;
|
||||
pdv[facei] = ddi - dni;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(patchD, faceI)
|
||||
forAll(patchD, facei)
|
||||
{
|
||||
const vector& ddi = patchD[faceI];
|
||||
const vector& dni = nbrPatchD[faceI];
|
||||
const vector& ddi = patchD[facei];
|
||||
const vector& dni = nbrPatchD[facei];
|
||||
|
||||
pdv[faceI] = ddi - transform(forwardT()[0], dni);
|
||||
pdv[facei] = ddi - transform(forwardT()[0], dni);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,10 +174,11 @@ public:
|
||||
//- Return delta (P to N) vectors across coupled patch
|
||||
virtual tmp<vectorField> delta() const;
|
||||
|
||||
//- Interpolate (make sure to have uptodate areas)
|
||||
template<class Type>
|
||||
tmp<Field<Type>> interpolate
|
||||
(
|
||||
const Field<Type>& fldCoupled
|
||||
const Field<Type>& fld
|
||||
) const
|
||||
{
|
||||
updateAreas();
|
||||
@ -185,57 +186,18 @@ public:
|
||||
return
|
||||
cyclicACMIPolyPatch_.cyclicAMIPolyPatch::interpolate
|
||||
(
|
||||
fldCoupled
|
||||
fld
|
||||
);
|
||||
}
|
||||
|
||||
//- Interpolate (make sure to have uptodate areas)
|
||||
template<class Type>
|
||||
tmp<Field<Type>> interpolate
|
||||
(
|
||||
const tmp<Field<Type>>& tfldCoupled
|
||||
const tmp<Field<Type>>& tfld
|
||||
) const
|
||||
{
|
||||
updateAreas();
|
||||
|
||||
return
|
||||
cyclicACMIPolyPatch_.cyclicAMIPolyPatch::interpolate
|
||||
(
|
||||
tfldCoupled
|
||||
);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
tmp<Field<Type>> interpolate
|
||||
(
|
||||
const Field<Type>& fldCoupled,
|
||||
const Field<Type>& fldNonOverlap
|
||||
) const
|
||||
{
|
||||
updateAreas();
|
||||
|
||||
return
|
||||
cyclicACMIPolyPatch_.interpolate
|
||||
(
|
||||
fldCoupled,
|
||||
fldNonOverlap
|
||||
);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
tmp<Field<Type>> interpolate
|
||||
(
|
||||
const tmp<Field<Type>>& tFldCoupled,
|
||||
const tmp<Field<Type>>& tFldNonOverlap
|
||||
) const
|
||||
{
|
||||
updateAreas();
|
||||
|
||||
return
|
||||
cyclicACMIPolyPatch_.interpolate
|
||||
(
|
||||
tFldCoupled,
|
||||
tFldNonOverlap
|
||||
);
|
||||
return interpolate(tfld());
|
||||
}
|
||||
|
||||
|
||||
|
@ -378,10 +378,17 @@ public:
|
||||
//- Return const access to source patch weights
|
||||
inline const scalarListList& srcWeights() const;
|
||||
|
||||
//- Return access to source patch weights
|
||||
inline scalarListList& srcWeights();
|
||||
|
||||
//- Return const access to normalisation factor of source
|
||||
// patch weights (i.e. the sum before normalisation)
|
||||
inline const scalarField& srcWeightsSum() const;
|
||||
|
||||
//- Return access to normalisation factor of source
|
||||
// patch weights (i.e. the sum before normalisation)
|
||||
inline scalarField& srcWeightsSum();
|
||||
|
||||
//- Source map pointer - valid only if singlePatchProc = -1
|
||||
// This gets source data into a form to be consumed by
|
||||
// tgtAddress, tgtWeights
|
||||
@ -399,10 +406,17 @@ public:
|
||||
//- Return const access to target patch weights
|
||||
inline const scalarListList& tgtWeights() const;
|
||||
|
||||
//- Return access to target patch weights
|
||||
inline scalarListList& tgtWeights();
|
||||
|
||||
//- Return const access to normalisation factor of target
|
||||
// patch weights (i.e. the sum before normalisation)
|
||||
inline const scalarField& tgtWeightsSum() const;
|
||||
|
||||
//- Return access to normalisation factor of target
|
||||
// patch weights (i.e. the sum before normalisation)
|
||||
inline scalarField& tgtWeightsSum();
|
||||
|
||||
//- Target map pointer - valid only if singlePatchProc=-1.
|
||||
// This gets target data into a form to be consumed by
|
||||
// srcAddress, srcWeights
|
||||
@ -533,7 +547,7 @@ public:
|
||||
const SourcePatch& srcPatch,
|
||||
const TargetPatch& tgtPatch,
|
||||
const vector& n,
|
||||
const label tgtFaceI,
|
||||
const label tgtFacei,
|
||||
point& tgtPoint
|
||||
)
|
||||
const;
|
||||
@ -544,7 +558,7 @@ public:
|
||||
const SourcePatch& srcPatch,
|
||||
const TargetPatch& tgtPatch,
|
||||
const vector& n,
|
||||
const label srcFaceI,
|
||||
const label srcFacei,
|
||||
point& srcPoint
|
||||
)
|
||||
const;
|
||||
|
@ -72,6 +72,14 @@ Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcWeights() const
|
||||
}
|
||||
|
||||
|
||||
template<class SourcePatch, class TargetPatch>
|
||||
inline Foam::scalarListList&
|
||||
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcWeights()
|
||||
{
|
||||
return srcWeights_;
|
||||
}
|
||||
|
||||
|
||||
template<class SourcePatch, class TargetPatch>
|
||||
inline const Foam::scalarField&
|
||||
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcWeightsSum() const
|
||||
@ -80,6 +88,14 @@ Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcWeightsSum() const
|
||||
}
|
||||
|
||||
|
||||
template<class SourcePatch, class TargetPatch>
|
||||
inline Foam::scalarField&
|
||||
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcWeightsSum()
|
||||
{
|
||||
return srcWeightsSum_;
|
||||
}
|
||||
|
||||
|
||||
template<class SourcePatch, class TargetPatch>
|
||||
inline const Foam::mapDistribute&
|
||||
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcMap() const
|
||||
@ -112,6 +128,14 @@ Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtWeights() const
|
||||
}
|
||||
|
||||
|
||||
template<class SourcePatch, class TargetPatch>
|
||||
inline Foam::scalarListList&
|
||||
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtWeights()
|
||||
{
|
||||
return tgtWeights_;
|
||||
}
|
||||
|
||||
|
||||
template<class SourcePatch, class TargetPatch>
|
||||
inline const Foam::scalarField&
|
||||
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtWeightsSum() const
|
||||
@ -120,6 +144,14 @@ Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtWeightsSum() const
|
||||
}
|
||||
|
||||
|
||||
template<class SourcePatch, class TargetPatch>
|
||||
inline Foam::scalarField&
|
||||
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtWeightsSum()
|
||||
{
|
||||
return tgtWeightsSum_;
|
||||
}
|
||||
|
||||
|
||||
template<class SourcePatch, class TargetPatch>
|
||||
inline const Foam::mapDistribute&
|
||||
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtMap() const
|
||||
|
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2013-2016 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -38,35 +38,10 @@ namespace Foam
|
||||
addToRunTimeSelectionTable(polyPatch, cyclicACMIPolyPatch, dictionary);
|
||||
}
|
||||
|
||||
const Foam::scalar Foam::cyclicACMIPolyPatch::tolerance_ = 1e-6;
|
||||
const Foam::scalar Foam::cyclicACMIPolyPatch::tolerance_ = 1e-10;
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::cyclicACMIPolyPatch::initPatchFaceAreas() const
|
||||
{
|
||||
if
|
||||
(
|
||||
!empty()
|
||||
&& (faceAreas0_.empty() || boundaryMesh().mesh().moving())
|
||||
)
|
||||
{
|
||||
faceAreas0_ = faceAreas();
|
||||
}
|
||||
|
||||
const cyclicACMIPolyPatch& nbrACMI =
|
||||
refCast<const cyclicACMIPolyPatch>(this->neighbPatch());
|
||||
|
||||
if
|
||||
(
|
||||
!nbrACMI.empty()
|
||||
&& (nbrACMI.faceAreas0().empty() || boundaryMesh().mesh().moving())
|
||||
)
|
||||
{
|
||||
nbrACMI.faceAreas0_ = nbrACMI.faceAreas();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::cyclicACMIPolyPatch::resetAMI
|
||||
(
|
||||
const AMIPatchToPatchInterpolation::interpolationMethod&
|
||||
@ -76,37 +51,117 @@ void Foam::cyclicACMIPolyPatch::resetAMI
|
||||
{
|
||||
const polyPatch& nonOverlapPatch = this->nonOverlapPatch();
|
||||
|
||||
initPatchFaceAreas();
|
||||
|
||||
// Reset patch face areas based on original patch for AMI calculation
|
||||
vectorField::subField Sf = faceAreas();
|
||||
vectorField::subField noSf = nonOverlapPatch.faceAreas();
|
||||
|
||||
forAll(Sf, faceI)
|
||||
if (debug)
|
||||
{
|
||||
Sf[faceI] = faceAreas0_[faceI];
|
||||
noSf[faceI] = faceAreas0_[faceI];
|
||||
Pout<< "cyclicACMIPolyPatch::resetAMI : recalculating weights"
|
||||
<< " for " << name() << " and " << nonOverlapPatch.name()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Calculate the AMI using partial face-area-weighted
|
||||
if (boundaryMesh().mesh().hasCellCentres())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "The mesh already has cellCentres calculated when"
|
||||
<< " resetting ACMI " << name() << "." << endl
|
||||
<< "This is a problem since ACMI adapts the face areas"
|
||||
<< " (to close cells) so this has" << endl
|
||||
<< "to be done before cell centre calculation." << endl
|
||||
<< "This can happen if e.g. the cyclicACMI is after"
|
||||
<< " any processor patches in the boundary." << endl
|
||||
<< "Continuing with potential for incorrect geometry"
|
||||
<< " calculation and mass loss" << endl;
|
||||
}
|
||||
|
||||
|
||||
// Trigger re-building of faceAreas
|
||||
(void)boundaryMesh().mesh().faceAreas();
|
||||
|
||||
|
||||
// Calculate the AMI using partial face-area-weighted. This leaves
|
||||
// the weights as fractions of local areas (sum(weights) = 1 means
|
||||
// face is fully covered)
|
||||
cyclicAMIPolyPatch::resetAMI
|
||||
(
|
||||
AMIPatchToPatchInterpolation::imPartialFaceAreaWeight
|
||||
);
|
||||
|
||||
AMIPatchToPatchInterpolation& AMI =
|
||||
const_cast<AMIPatchToPatchInterpolation&>(this->AMI());
|
||||
|
||||
srcMask_ =
|
||||
min(scalar(1) - tolerance_, max(tolerance_, AMI().srcWeightsSum()));
|
||||
min(scalar(1) - tolerance_, max(tolerance_, AMI.srcWeightsSum()));
|
||||
|
||||
tgtMask_ =
|
||||
min(scalar(1) - tolerance_, max(tolerance_, AMI().tgtWeightsSum()));
|
||||
min(scalar(1) - tolerance_, max(tolerance_, AMI.tgtWeightsSum()));
|
||||
|
||||
forAll(Sf, faceI)
|
||||
|
||||
// Adapt owner side areas. Note that in uncoupled situations (e.g.
|
||||
// decomposePar) srcMask, tgtMask can be zero size.
|
||||
if (srcMask_.size())
|
||||
{
|
||||
Sf[faceI] *= srcMask_[faceI];
|
||||
noSf[faceI] *= 1.0 - srcMask_[faceI];
|
||||
vectorField::subField Sf = faceAreas();
|
||||
vectorField::subField noSf = nonOverlapPatch.faceAreas();
|
||||
|
||||
forAll(Sf, facei)
|
||||
{
|
||||
Sf[facei] *= srcMask_[facei];
|
||||
noSf[facei] *= 1.0 - srcMask_[facei];
|
||||
}
|
||||
}
|
||||
// Adapt slave side areas
|
||||
if (tgtMask_.size())
|
||||
{
|
||||
const cyclicACMIPolyPatch& cp =
|
||||
refCast<const cyclicACMIPolyPatch>(this->neighbPatch());
|
||||
const polyPatch& pp = cp.nonOverlapPatch();
|
||||
|
||||
vectorField::subField Sf = cp.faceAreas();
|
||||
vectorField::subField noSf = pp.faceAreas();
|
||||
|
||||
forAll(Sf, facei)
|
||||
{
|
||||
Sf[facei] *= tgtMask_[facei];
|
||||
noSf[facei] *= 1.0 - tgtMask_[facei];
|
||||
}
|
||||
}
|
||||
|
||||
setNeighbourFaceAreas();
|
||||
// Re-normalise the weights since the effect of overlap is already
|
||||
// accounted for in the area.
|
||||
{
|
||||
scalarListList& srcWeights = AMI.srcWeights();
|
||||
scalarField& srcWeightsSum = AMI.srcWeightsSum();
|
||||
forAll(srcWeights, i)
|
||||
{
|
||||
scalarList& wghts = srcWeights[i];
|
||||
if (wghts.size())
|
||||
{
|
||||
scalar& sum = srcWeightsSum[i];
|
||||
|
||||
forAll(wghts, j)
|
||||
{
|
||||
wghts[j] /= sum;
|
||||
}
|
||||
sum = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
scalarListList& tgtWeights = AMI.tgtWeights();
|
||||
scalarField& tgtWeightsSum = AMI.tgtWeightsSum();
|
||||
forAll(tgtWeights, i)
|
||||
{
|
||||
scalarList& wghts = tgtWeights[i];
|
||||
if (wghts.size())
|
||||
{
|
||||
scalar& sum = tgtWeightsSum[i];
|
||||
forAll(wghts, j)
|
||||
{
|
||||
wghts[j] /= sum;
|
||||
}
|
||||
sum = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the updated flag
|
||||
updated_ = true;
|
||||
@ -114,48 +169,26 @@ void Foam::cyclicACMIPolyPatch::resetAMI
|
||||
}
|
||||
|
||||
|
||||
void Foam::cyclicACMIPolyPatch::setNeighbourFaceAreas() const
|
||||
{
|
||||
const cyclicACMIPolyPatch& cp =
|
||||
refCast<const cyclicACMIPolyPatch>(this->neighbPatch());
|
||||
const polyPatch& pp = cp.nonOverlapPatch();
|
||||
|
||||
const vectorField& faceAreas0 = cp.faceAreas0();
|
||||
|
||||
if (tgtMask_.size() == cp.size())
|
||||
{
|
||||
vectorField::subField Sf = cp.faceAreas();
|
||||
vectorField::subField noSf = pp.faceAreas();
|
||||
|
||||
forAll(Sf, faceI)
|
||||
{
|
||||
Sf[faceI] = tgtMask_[faceI]*faceAreas0[faceI];
|
||||
noSf[faceI] = (1.0 - tgtMask_[faceI])*faceAreas0[faceI];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Target mask size differs to that of the neighbour patch\n"
|
||||
<< " May occur when decomposing." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::cyclicACMIPolyPatch::initGeometry(PstreamBuffers& pBufs)
|
||||
{
|
||||
// Note: cyclicAMIPolyPatch clears AMI so do first
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "cyclicACMIPolyPatch::initGeometry : " << name() << endl;
|
||||
}
|
||||
|
||||
cyclicAMIPolyPatch::initGeometry(pBufs);
|
||||
|
||||
// Initialise the AMI so that base geometry (e.g. cell volumes) are
|
||||
// correctly evaluated before e.g. any of the processor patches gets
|
||||
// hit (since uses cell volumes in its initGeometry)
|
||||
// Initialise the AMI
|
||||
resetAMI();
|
||||
}
|
||||
|
||||
|
||||
void Foam::cyclicACMIPolyPatch::calcGeometry(PstreamBuffers& pBufs)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "cyclicACMIPolyPatch::calcGeometry : " << name() << endl;
|
||||
}
|
||||
cyclicAMIPolyPatch::calcGeometry(pBufs);
|
||||
}
|
||||
|
||||
@ -166,12 +199,13 @@ void Foam::cyclicACMIPolyPatch::initMovePoints
|
||||
const pointField& p
|
||||
)
|
||||
{
|
||||
// Note: cyclicAMIPolyPatch clears AMI so do first
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "cyclicACMIPolyPatch::initMovePoints : " << name() << endl;
|
||||
}
|
||||
cyclicAMIPolyPatch::initMovePoints(pBufs, p);
|
||||
|
||||
// Initialise the AMI so that base geometry (e.g. cell volumes) are
|
||||
// correctly evaluated before e.g. any of the processor patches gets
|
||||
// hit (since uses cell volumes in its initGeometry)
|
||||
// Initialise the AMI
|
||||
resetAMI();
|
||||
}
|
||||
|
||||
@ -182,24 +216,40 @@ void Foam::cyclicACMIPolyPatch::movePoints
|
||||
const pointField& p
|
||||
)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "cyclicACMIPolyPatch::movePoints : " << name() << endl;
|
||||
}
|
||||
cyclicAMIPolyPatch::movePoints(pBufs, p);
|
||||
}
|
||||
|
||||
|
||||
void Foam::cyclicACMIPolyPatch::initUpdateMesh(PstreamBuffers& pBufs)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "cyclicACMIPolyPatch::initUpdateMesh : " << name() << endl;
|
||||
}
|
||||
cyclicAMIPolyPatch::initUpdateMesh(pBufs);
|
||||
}
|
||||
|
||||
|
||||
void Foam::cyclicACMIPolyPatch::updateMesh(PstreamBuffers& pBufs)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "cyclicACMIPolyPatch::updateMesh : " << name() << endl;
|
||||
}
|
||||
cyclicAMIPolyPatch::updateMesh(pBufs);
|
||||
}
|
||||
|
||||
|
||||
void Foam::cyclicACMIPolyPatch::clearGeom()
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "cyclicACMIPolyPatch::clearGeom : " << name() << endl;
|
||||
}
|
||||
cyclicAMIPolyPatch::clearGeom();
|
||||
}
|
||||
|
||||
@ -230,7 +280,6 @@ Foam::cyclicACMIPolyPatch::cyclicACMIPolyPatch
|
||||
)
|
||||
:
|
||||
cyclicAMIPolyPatch(name, size, start, index, bm, patchType, transform),
|
||||
faceAreas0_(),
|
||||
nonOverlapPatchName_(word::null),
|
||||
nonOverlapPatchID_(-1),
|
||||
srcMask_(),
|
||||
@ -254,7 +303,6 @@ Foam::cyclicACMIPolyPatch::cyclicACMIPolyPatch
|
||||
)
|
||||
:
|
||||
cyclicAMIPolyPatch(name, dict, index, bm, patchType),
|
||||
faceAreas0_(),
|
||||
nonOverlapPatchName_(dict.lookup("nonOverlapPatch")),
|
||||
nonOverlapPatchID_(-1),
|
||||
srcMask_(),
|
||||
@ -285,7 +333,6 @@ Foam::cyclicACMIPolyPatch::cyclicACMIPolyPatch
|
||||
)
|
||||
:
|
||||
cyclicAMIPolyPatch(pp, bm),
|
||||
faceAreas0_(),
|
||||
nonOverlapPatchName_(pp.nonOverlapPatchName_),
|
||||
nonOverlapPatchID_(-1),
|
||||
srcMask_(),
|
||||
@ -311,7 +358,6 @@ Foam::cyclicACMIPolyPatch::cyclicACMIPolyPatch
|
||||
)
|
||||
:
|
||||
cyclicAMIPolyPatch(pp, bm, index, newSize, newStart, nbrPatchName),
|
||||
faceAreas0_(),
|
||||
nonOverlapPatchName_(nonOverlapPatchName),
|
||||
nonOverlapPatchID_(-1),
|
||||
srcMask_(),
|
||||
@ -343,7 +389,6 @@ Foam::cyclicACMIPolyPatch::cyclicACMIPolyPatch
|
||||
)
|
||||
:
|
||||
cyclicAMIPolyPatch(pp, bm, index, mapAddressing, newStart),
|
||||
faceAreas0_(),
|
||||
nonOverlapPatchName_(pp.nonOverlapPatchName_),
|
||||
nonOverlapPatchID_(-1),
|
||||
srcMask_(),
|
||||
@ -406,9 +451,9 @@ Foam::label Foam::cyclicACMIPolyPatch::nonOverlapPatchID() const
|
||||
const scalarField magSf(mag(faceAreas()));
|
||||
const scalarField noMagSf(mag(noPp.faceAreas()));
|
||||
|
||||
forAll(magSf, faceI)
|
||||
forAll(magSf, facei)
|
||||
{
|
||||
scalar ratio = mag(magSf[faceI]/(noMagSf[faceI] + ROOTVSMALL));
|
||||
scalar ratio = mag(magSf[facei]/(noMagSf[facei] + ROOTVSMALL));
|
||||
|
||||
if (ratio - 1 > tolerance_)
|
||||
{
|
||||
|
@ -57,8 +57,8 @@ private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- Copy of the original patch face areas
|
||||
mutable vectorField faceAreas0_;
|
||||
//- Fraction of face area below which face is considered disconnected
|
||||
static const scalar tolerance_;
|
||||
|
||||
//- Name of non-overlapping patch
|
||||
const word nonOverlapPatchName_;
|
||||
@ -78,14 +78,8 @@ private:
|
||||
|
||||
protected:
|
||||
|
||||
static const scalar tolerance_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Initialise patch face areas
|
||||
virtual void initPatchFaceAreas() const;
|
||||
|
||||
//- Reset the AMI interpolator
|
||||
virtual void resetAMI
|
||||
(
|
||||
@ -93,9 +87,6 @@ protected:
|
||||
AMIPatchToPatchInterpolation::imFaceAreaWeight
|
||||
) const;
|
||||
|
||||
//- Set neighbour ACMI patch areas
|
||||
virtual void setNeighbourFaceAreas() const;
|
||||
|
||||
//- Initialise the calculation of the patch geometry
|
||||
virtual void initGeometry(PstreamBuffers&);
|
||||
|
||||
@ -254,9 +245,6 @@ public:
|
||||
//- Return access to the updated flag
|
||||
inline bool updated() const;
|
||||
|
||||
//- Return access to the original patch face areas
|
||||
inline const vectorField& faceAreas0() const;
|
||||
|
||||
//- Return a reference to the neighbour patch
|
||||
virtual const cyclicACMIPolyPatch& neighbPatch() const;
|
||||
|
||||
@ -275,34 +263,8 @@ public:
|
||||
//- Mask field where 1 = overlap, 0 = no-overlap
|
||||
inline const scalarField& mask() const;
|
||||
|
||||
|
||||
// Interpolations
|
||||
|
||||
//- Interpolate field
|
||||
template<class Type>
|
||||
tmp<Field<Type>> interpolate
|
||||
(
|
||||
const Field<Type>& fldCouple,
|
||||
const Field<Type>& fldNonOverlap
|
||||
) const;
|
||||
|
||||
//- Interpolate tmp field
|
||||
template<class Type>
|
||||
tmp<Field<Type>> interpolate
|
||||
(
|
||||
const tmp<Field<Type>>& tFldCouple,
|
||||
const tmp<Field<Type>>& tFldNonOverlap
|
||||
) const;
|
||||
|
||||
//- Low-level interpolate List
|
||||
template<class Type, class CombineOp>
|
||||
void interpolate
|
||||
(
|
||||
const UList<Type>& fldCouple,
|
||||
const UList<Type>& fldNonOverlap,
|
||||
const CombineOp& cop,
|
||||
List<Type>& result
|
||||
) const;
|
||||
//- Overlap tolerance
|
||||
inline static scalar tolerance();
|
||||
|
||||
|
||||
//- Calculate the patch geometry
|
||||
@ -353,12 +315,6 @@ public:
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "cyclicACMIPolyPatchTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2013-2016 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -37,12 +37,6 @@ inline bool Foam::cyclicACMIPolyPatch::updated() const
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::vectorField& Foam::cyclicACMIPolyPatch::faceAreas0() const
|
||||
{
|
||||
return faceAreas0_;
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::word& Foam::cyclicACMIPolyPatch::nonOverlapPatchName() const
|
||||
{
|
||||
return nonOverlapPatchName_;
|
||||
@ -80,4 +74,10 @@ inline const Foam::scalarField& Foam::cyclicACMIPolyPatch::mask() const
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar Foam::cyclicACMIPolyPatch::tolerance()
|
||||
{
|
||||
return tolerance_;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
@ -1,102 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2016 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>> Foam::cyclicACMIPolyPatch::interpolate
|
||||
(
|
||||
const Field<Type>& fldCouple,
|
||||
const Field<Type>& fldNonOverlap
|
||||
) const
|
||||
{
|
||||
// Note: do not scale AMI field as face areas have already been taken
|
||||
// into account
|
||||
|
||||
if (owner())
|
||||
{
|
||||
const scalarField& w = AMI().srcWeightsSum();
|
||||
|
||||
tmp<Field<Type>> interpField(AMI().interpolateToSource(fldCouple));
|
||||
|
||||
return interpField + (1.0 - w)*fldNonOverlap;
|
||||
}
|
||||
else
|
||||
{
|
||||
const scalarField& w = neighbPatch().AMI().tgtWeightsSum();
|
||||
|
||||
tmp<Field<Type>> interpField
|
||||
(
|
||||
neighbPatch().AMI().interpolateToTarget(fldCouple)
|
||||
);
|
||||
|
||||
return interpField + (1.0 - w)*fldNonOverlap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>> Foam::cyclicACMIPolyPatch::interpolate
|
||||
(
|
||||
const tmp<Field<Type>>& tFldCouple,
|
||||
const tmp<Field<Type>>& tFldNonOverlap
|
||||
) const
|
||||
{
|
||||
return interpolate(tFldCouple(), tFldNonOverlap());
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
void Foam::cyclicACMIPolyPatch::interpolate
|
||||
(
|
||||
const UList<Type>& fldCouple,
|
||||
const UList<Type>& fldNonOverlap,
|
||||
const CombineOp& cop,
|
||||
List<Type>& result
|
||||
) const
|
||||
{
|
||||
// Note: do not scale AMI field as face areas have already been taken
|
||||
// into account
|
||||
|
||||
if (owner())
|
||||
{
|
||||
const scalarField& w = AMI().srcWeightsSum();
|
||||
|
||||
AMI().interpolateToSource(fldCouple, cop, result);
|
||||
|
||||
result = result + (1.0 - w)*fldNonOverlap;
|
||||
}
|
||||
else
|
||||
{
|
||||
const scalarField& w = neighbPatch().AMI().tgtWeightsSum();
|
||||
|
||||
neighbPatch().AMI().interpolateToTarget(fldCouple, cop, result);
|
||||
|
||||
result = result + (1.0 - w)*fldNonOverlap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
@ -35,7 +35,7 @@ purgeWrite 0;
|
||||
|
||||
writeFormat ascii;
|
||||
|
||||
writePrecision 6;
|
||||
writePrecision 10;
|
||||
|
||||
writeCompression off;
|
||||
|
||||
|
@ -39,7 +39,7 @@ solvers
|
||||
pFinal
|
||||
{
|
||||
$p;
|
||||
tolerance 1e-6;
|
||||
tolerance 1e-10;
|
||||
relTol 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user