Added option for zonal under-relaxation
This commit is contained in:
parent
a8599a8f9a
commit
a8ddd0885f
2 changed files with 158 additions and 16 deletions
|
@ -56,7 +56,7 @@ void Foam::fvMatrix<Type>::addToInternalField
|
||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
forAll(addr, faceI)
|
forAll (addr, faceI)
|
||||||
{
|
{
|
||||||
intf[addr[faceI]] += pf[faceI];
|
intf[addr[faceI]] += pf[faceI];
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ void Foam::fvMatrix<Type>::subtractFromInternalField
|
||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
forAll(addr, faceI)
|
forAll (addr, faceI)
|
||||||
{
|
{
|
||||||
intf[addr[faceI]] -= pf[faceI];
|
intf[addr[faceI]] -= pf[faceI];
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ void Foam::fvMatrix<Type>::addBoundaryDiag
|
||||||
const direction solveCmpt
|
const direction solveCmpt
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
forAll(internalCoeffs_, patchI)
|
forAll (internalCoeffs_, patchI)
|
||||||
{
|
{
|
||||||
addToInternalField
|
addToInternalField
|
||||||
(
|
(
|
||||||
|
@ -139,7 +139,7 @@ void Foam::fvMatrix<Type>::addBoundaryDiag
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void Foam::fvMatrix<Type>::addCmptAvBoundaryDiag(scalarField& diag) const
|
void Foam::fvMatrix<Type>::addCmptAvBoundaryDiag(scalarField& diag) const
|
||||||
{
|
{
|
||||||
forAll(internalCoeffs_, patchI)
|
forAll (internalCoeffs_, patchI)
|
||||||
{
|
{
|
||||||
addToInternalField
|
addToInternalField
|
||||||
(
|
(
|
||||||
|
@ -158,7 +158,7 @@ void Foam::fvMatrix<Type>::addBoundarySource
|
||||||
const bool couples
|
const bool couples
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
forAll(psi_.boundaryField(), patchI)
|
forAll (psi_.boundaryField(), patchI)
|
||||||
{
|
{
|
||||||
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
||||||
const Field<Type>& pbc = boundaryCoeffs_[patchI];
|
const Field<Type>& pbc = boundaryCoeffs_[patchI];
|
||||||
|
@ -190,7 +190,7 @@ void Foam::fvMatrix<Type>::correctImplicitBoundarySource
|
||||||
const direction cmpt
|
const direction cmpt
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
forAll(psi_.boundaryField(), patchI)
|
forAll (psi_.boundaryField(), patchI)
|
||||||
{
|
{
|
||||||
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
||||||
const scalarField& pbc = bouCoeffsCmpt[patchI];
|
const scalarField& pbc = bouCoeffsCmpt[patchI];
|
||||||
|
@ -492,7 +492,7 @@ void Foam::fvMatrix<Type>::setValues
|
||||||
GeometricField<Type, fvPatchField, volMesh>&
|
GeometricField<Type, fvPatchField, volMesh>&
|
||||||
>(psi_).internalField();
|
>(psi_).internalField();
|
||||||
|
|
||||||
forAll(cellLabels, i)
|
forAll (cellLabels, i)
|
||||||
{
|
{
|
||||||
label celli = cellLabels[i];
|
label celli = cellLabels[i];
|
||||||
|
|
||||||
|
@ -503,7 +503,7 @@ void Foam::fvMatrix<Type>::setValues
|
||||||
{
|
{
|
||||||
const cell& c = cells[celli];
|
const cell& c = cells[celli];
|
||||||
|
|
||||||
forAll(c, j)
|
forAll (c, j)
|
||||||
{
|
{
|
||||||
label facei = c[j];
|
label facei = c[j];
|
||||||
|
|
||||||
|
@ -622,7 +622,7 @@ void Foam::fvMatrix<Type>::relax(const scalar alpha)
|
||||||
sumMagOffDiag(sumOff);
|
sumMagOffDiag(sumOff);
|
||||||
|
|
||||||
// Handle the boundary contributions to the diagonal
|
// Handle the boundary contributions to the diagonal
|
||||||
forAll(psi_.boundaryField(), patchI)
|
forAll (psi_.boundaryField(), patchI)
|
||||||
{
|
{
|
||||||
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
||||||
|
|
||||||
|
@ -637,7 +637,7 @@ void Foam::fvMatrix<Type>::relax(const scalar alpha)
|
||||||
|
|
||||||
// For coupled boundaries add the diagonal and
|
// For coupled boundaries add the diagonal and
|
||||||
// off-diagonal contributions
|
// off-diagonal contributions
|
||||||
forAll(pa, face)
|
forAll (pa, face)
|
||||||
{
|
{
|
||||||
D[pa[face]] += component(iCoeffs[face], 0);
|
D[pa[face]] += component(iCoeffs[face], 0);
|
||||||
sumOff[pa[face]] += mag(component(pCoeffs[face], 0));
|
sumOff[pa[face]] += mag(component(pCoeffs[face], 0));
|
||||||
|
@ -649,7 +649,7 @@ void Foam::fvMatrix<Type>::relax(const scalar alpha)
|
||||||
// contribution off-diagonal sum which avoids having to remove
|
// contribution off-diagonal sum which avoids having to remove
|
||||||
// it from the diagonal later.
|
// it from the diagonal later.
|
||||||
// Also add the source contribution from the relaxation
|
// Also add the source contribution from the relaxation
|
||||||
forAll(pa, face)
|
forAll (pa, face)
|
||||||
{
|
{
|
||||||
Type iCoeff0 = iCoeffs[face];
|
Type iCoeff0 = iCoeffs[face];
|
||||||
iCoeffs[face] = cmptMag(iCoeffs[face]);
|
iCoeffs[face] = cmptMag(iCoeffs[face]);
|
||||||
|
@ -669,7 +669,7 @@ void Foam::fvMatrix<Type>::relax(const scalar alpha)
|
||||||
D /= alpha;
|
D /= alpha;
|
||||||
|
|
||||||
// Now remove the diagonal contribution from coupled boundaries
|
// Now remove the diagonal contribution from coupled boundaries
|
||||||
forAll(psi_.boundaryField(), patchI)
|
forAll (psi_.boundaryField(), patchI)
|
||||||
{
|
{
|
||||||
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
||||||
|
|
||||||
|
@ -680,7 +680,7 @@ void Foam::fvMatrix<Type>::relax(const scalar alpha)
|
||||||
|
|
||||||
if (ptf.coupled())
|
if (ptf.coupled())
|
||||||
{
|
{
|
||||||
forAll(pa, face)
|
forAll (pa, face)
|
||||||
{
|
{
|
||||||
D[pa[face]] -= component(iCoeffs[face], 0);
|
D[pa[face]] -= component(iCoeffs[face], 0);
|
||||||
}
|
}
|
||||||
|
@ -715,6 +715,140 @@ void Foam::fvMatrix<Type>::relax()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void Foam::fvMatrix<Type>::relax
|
||||||
|
(
|
||||||
|
const scalar alpha,
|
||||||
|
const word& cellZoneName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (alpha <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find cell zone and check it is not empty
|
||||||
|
const label zoneID = psi_.mesh().cellZones().findZoneID(cellZoneName);
|
||||||
|
|
||||||
|
if (zoneID < 0)
|
||||||
|
{
|
||||||
|
WarningIn
|
||||||
|
(
|
||||||
|
"void fvMatrix<Type>::relax\n"
|
||||||
|
"(\n"
|
||||||
|
" const scalar alpha,\n"
|
||||||
|
" const word& cellZoneName\n"
|
||||||
|
")"
|
||||||
|
) << "Cannot find cell zone " << cellZoneName
|
||||||
|
<< ". No relaxation applied"
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (psi_.mesh().cellZones()[zoneID].empty())
|
||||||
|
{
|
||||||
|
// Zone empty, skip
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Field<Type>& S = source();
|
||||||
|
scalarField& D = diag();
|
||||||
|
|
||||||
|
// Store the current unrelaxed diagonal for use in updating the source
|
||||||
|
scalarField D0(D);
|
||||||
|
|
||||||
|
// Calculate the sum-mag off-diagonal from the interior faces
|
||||||
|
scalarField sumOff(D.size(), 0.0);
|
||||||
|
sumMagOffDiag(sumOff);
|
||||||
|
|
||||||
|
// Handle the boundary contributions to the diagonal
|
||||||
|
forAll (psi_.boundaryField(), patchI)
|
||||||
|
{
|
||||||
|
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
||||||
|
|
||||||
|
if (ptf.size())
|
||||||
|
{
|
||||||
|
const unallocLabelList& pa = lduAddr().patchAddr(patchI);
|
||||||
|
Field<Type>& iCoeffs = internalCoeffs_[patchI];
|
||||||
|
|
||||||
|
if (ptf.coupled())
|
||||||
|
{
|
||||||
|
const Field<Type>& pCoeffs = boundaryCoeffs_[patchI];
|
||||||
|
|
||||||
|
// For coupled boundaries add the diagonal and
|
||||||
|
// off-diagonal contributions
|
||||||
|
forAll (pa, face)
|
||||||
|
{
|
||||||
|
D[pa[face]] += component(iCoeffs[face], 0);
|
||||||
|
sumOff[pa[face]] += mag(component(pCoeffs[face], 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For non-coupled boundaries subtract the diagonal
|
||||||
|
// contribution off-diagonal sum which avoids having to remove
|
||||||
|
// it from the diagonal later.
|
||||||
|
// Also add the source contribution from the relaxation
|
||||||
|
forAll (pa, face)
|
||||||
|
{
|
||||||
|
Type iCoeff0 = iCoeffs[face];
|
||||||
|
iCoeffs[face] = cmptMag(iCoeffs[face]);
|
||||||
|
sumOff[pa[face]] -= cmptMin(iCoeffs[face]);
|
||||||
|
iCoeffs[face] /= alpha;
|
||||||
|
S[pa[face]] +=
|
||||||
|
cmptMultiply(iCoeffs[face] - iCoeff0, psi_[pa[face]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Under-relax only cells within the zone
|
||||||
|
const labelList& zoneCells = psi_.mesh().cellZones()[zoneID];
|
||||||
|
|
||||||
|
forAll (zoneCells, zcI)
|
||||||
|
{
|
||||||
|
const label cellI = zoneCells[zcI];
|
||||||
|
|
||||||
|
// Ensure the matrix is diagonally dominant...
|
||||||
|
D[cellI] = max(D[cellI], sumOff[cellI]);
|
||||||
|
|
||||||
|
// ... then relax
|
||||||
|
D[cellI] /= alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now remove the diagonal contribution from coupled boundaries
|
||||||
|
forAll (psi_.boundaryField(), patchI)
|
||||||
|
{
|
||||||
|
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
||||||
|
|
||||||
|
if (ptf.size())
|
||||||
|
{
|
||||||
|
const unallocLabelList& pa = lduAddr().patchAddr(patchI);
|
||||||
|
Field<Type>& iCoeffs = internalCoeffs_[patchI];
|
||||||
|
|
||||||
|
if (ptf.coupled())
|
||||||
|
{
|
||||||
|
forAll (pa, face)
|
||||||
|
{
|
||||||
|
D[pa[face]] -= component(iCoeffs[face], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Field<Type>& psiIn = psi_.internalField();
|
||||||
|
|
||||||
|
forAll (zoneCells, zcI)
|
||||||
|
{
|
||||||
|
const label cellI = zoneCells[zcI];
|
||||||
|
|
||||||
|
// Finally add the relaxation contribution to the source.
|
||||||
|
S[cellI] += (D[cellI] - D0[cellI])*psiIn[cellI];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void Foam::fvMatrix<Type>::completeAssembly()
|
void Foam::fvMatrix<Type>::completeAssembly()
|
||||||
{
|
{
|
||||||
|
@ -739,7 +873,7 @@ void Foam::fvMatrix<Type>::completeAssembly()
|
||||||
typename GeometricField<Type, fvPatchField, volMesh>::
|
typename GeometricField<Type, fvPatchField, volMesh>::
|
||||||
GeometricBoundaryField& bFields = ncPsi.boundaryField();
|
GeometricBoundaryField& bFields = ncPsi.boundaryField();
|
||||||
|
|
||||||
forAll(bFields, patchI)
|
forAll (bFields, patchI)
|
||||||
{
|
{
|
||||||
bFields[patchI].manipulateMatrix(*this);
|
bFields[patchI].manipulateMatrix(*this);
|
||||||
}
|
}
|
||||||
|
@ -760,7 +894,7 @@ Foam::tmp<Foam::Field<Type> > Foam::fvMatrix<Type>::DD() const
|
||||||
{
|
{
|
||||||
tmp<Field<Type> > tdiag(pTraits<Type>::one*diag());
|
tmp<Field<Type> > tdiag(pTraits<Type>::one*diag());
|
||||||
|
|
||||||
forAll(psi_.boundaryField(), patchI)
|
forAll (psi_.boundaryField(), patchI)
|
||||||
{
|
{
|
||||||
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
|
||||||
|
|
||||||
|
@ -1223,7 +1357,7 @@ void Foam::fvMatrix<Type>::operator*=
|
||||||
lduMatrix::operator*=(dsf.field());
|
lduMatrix::operator*=(dsf.field());
|
||||||
source_ *= dsf.field();
|
source_ *= dsf.field();
|
||||||
|
|
||||||
forAll(boundaryCoeffs_, patchI)
|
forAll (boundaryCoeffs_, patchI)
|
||||||
{
|
{
|
||||||
scalarField psf
|
scalarField psf
|
||||||
(
|
(
|
||||||
|
|
|
@ -357,6 +357,14 @@ public:
|
||||||
// alpha is read from controlDict
|
// alpha is read from controlDict
|
||||||
void relax();
|
void relax();
|
||||||
|
|
||||||
|
//- Relax matrix only within a cell zone
|
||||||
|
// Experimental
|
||||||
|
void relax
|
||||||
|
(
|
||||||
|
const scalar alpha,
|
||||||
|
const word& cellZoneName
|
||||||
|
);
|
||||||
|
|
||||||
//- Complete matrix assembly for solution:
|
//- Complete matrix assembly for solution:
|
||||||
// Manipulate based on a boundary field
|
// Manipulate based on a boundary field
|
||||||
void completeAssembly();
|
void completeAssembly();
|
||||||
|
|
Reference in a new issue