|
[Sponsors] |
why in solve(UEqn == -fvc::grad(p)) UEqn.source() is not modified and UEqn.H() chang |
|
LinkBack | Thread Tools | Search this Thread | Display Modes |
January 1, 2019, 12:26 |
why in solve(UEqn == -fvc::grad(p)) UEqn.source() is not modified and UEqn.H() chang
|
#1 |
Senior Member
Michael Alletto
Join Date: Jun 2018
Location: Bremen
Posts: 616
Rep Power: 16 |
Hello Foamers,
I have a fundamental question understanding simpleFoam. when solve(UEqn == -fvc::grad(p)); is called in simpleFoam the UEqn.source() not modified (i printed the UEqn.source() for a small cavity flow) but UEqn.H() is modified. from the source code in fvMatrix.C this is not to see. The operator == is defined as follows Code:
template<class Type> Foam::tmp<Foam::fvMatrix<Type>> Foam::operator== ( const fvMatrix<Type>& A, const DimensionedField<Type, volMesh>& su ) { checkMethod(A, su, "=="); tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A)); tC.ref().source() += su.mesh().V()*su.field(); return tC; } template<class Type> Foam::tmp<Foam::fvMatrix<Type>> Foam::operator== ( const fvMatrix<Type>& A, const tmp<DimensionedField<Type, volMesh>>& tsu ) { checkMethod(A, tsu(), "=="); tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A)); tC.ref().source() += tsu().mesh().V()*tsu().field(); tsu.clear(); return tC; } template<class Type> Foam::tmp<Foam::fvMatrix<Type>> Foam::operator== ( const fvMatrix<Type>& A, const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu ) { checkMethod(A, tsu(), "=="); tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A)); tC.ref().source() += tsu().mesh().V()*tsu().primitiveField(); tsu.clear(); return tC; } fvMatrix<Type>(A)) unchanged the function solve executes fvm.solve, clears the space and returns some statistics: Code:
template<class Type> Foam::SolverPerformance<Type> Foam::solve(const tmp<fvMatrix<Type>>& tfvm) { SolverPerformance<Type> solverPerf = const_cast<fvMatrix<Type>&>(tfvm()).solve(); tfvm.clear(); return solverPerf; } From this analysis I would guess that the matrix UEqn is solved with the addition of the pressure gradient but the H operator should not be changed. This is obviously in contrast from the printing of H and source during the iteration. What I also noticed is that the field U is also modified after calling solve(UEqn == -fvc::grad(p)); |
|
January 1, 2019, 12:59 |
|
#2 |
Senior Member
Michael Alletto
Join Date: Jun 2018
Location: Bremen
Posts: 616
Rep Power: 16 |
Ok maybe I can answer my question by myself:
When the matrix Code:
tmp<fvVectorMatrix> tUEqn ( fvm::div(phi, U) + MRF.DDt(U) + turbulence->divDevReff(U) == fvOptions(U) ); fvVectorMatrix& UEqn = tUEqn.ref(); is constructed the solution vector psi_ is defined as a reference to U: Code:
template<class Type> Foam::fvMatrix<Type>::fvMatrix ( const GeometricField<Type, fvPatchField, volMesh>& psi, const dimensionSet& ds ) : lduMatrix(psi.mesh()), psi_(psi), dimensions_(ds), source_(psi.size(), Zero), internalCoeffs_(psi.mesh().boundary().size()), boundaryCoeffs_(psi.mesh().boundary().size()), faceFluxCorrectionPtr_(nullptr) { if (debug) { InfoInFunction << "Constructing fvMatrix<Type> for field " << psi_.name() << endl; } // Initialise coupling coefficients forAll(psi.mesh().boundary(), patchi) { internalCoeffs_.set ( patchi, new Field<Type> ( psi.mesh().boundary()[patchi].size(), Zero ) ); boundaryCoeffs_.set ( patchi, new Field<Type> ( psi.mesh().boundary()[patchi].size(), Zero ) ); } // Update the boundary coefficients of psi without changing its event No. GeometricField<Type, fvPatchField, volMesh>& psiRef = const_cast<GeometricField<Type, fvPatchField, volMesh>&>(psi_); label currentStatePsi = psiRef.eventNo(); psiRef.boundaryFieldRef().updateCoeffs(); psiRef.eventNo() = currentStatePsi; } after that the function solve(UEqn == -fvc::grad(p)); is called. It indeed solves a new matrix (the old one where to the already existing source the pressure gradient is added). But when the matrix is solved, the solution vector psi_ is modified which is a reference to U. This is in line with the observation that U is modified after the solution of the matrix. Hence also the solution vector psi_ of UEqn is also modified. But the source of UEqn remains unchanged. since the H() is computed from the solution vector psi_ and the source: Code:
template<class Type> Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>> Foam::fvMatrix<Type>::H() const { tmp<GeometricField<Type, fvPatchField, volMesh>> tHphi ( new GeometricField<Type, fvPatchField, volMesh> ( IOobject ( "H("+psi_.name()+')', psi_.instance(), psi_.mesh(), IOobject::NO_READ, IOobject::NO_WRITE ), psi_.mesh(), dimensions_/dimVol, extrapolatedCalculatedFvPatchScalarField::typeName ) ); GeometricField<Type, fvPatchField, volMesh>& Hphi = tHphi.ref(); // Loop over field components for (direction cmpt=0; cmpt<Type::nComponents; cmpt++) { scalarField psiCmpt(psi_.primitiveField().component(cmpt)); scalarField boundaryDiagCmpt(psi_.size(), 0.0); addBoundaryDiag(boundaryDiagCmpt, cmpt); boundaryDiagCmpt.negate(); addCmptAvBoundaryDiag(boundaryDiagCmpt); Hphi.primitiveFieldRef().replace(cmpt, boundaryDiagCmpt*psiCmpt); } Hphi.primitiveFieldRef() += lduMatrix::H(psi_.primitiveField()) + source_; addBoundarySource(Hphi.primitiveFieldRef()); Hphi.primitiveFieldRef() /= psi_.mesh().V(); Hphi.correctBoundaryConditions(); typename Type::labelType validComponents ( psi_.mesh().template validComponents<Type>() ); for (direction cmpt=0; cmpt<Type::nComponents; cmpt++) { if (validComponents[cmpt] == -1) { Hphi.replace ( cmpt, dimensionedScalar("0", Hphi.dimensions(), 0.0) ); } } return tHphi; } this explains why the H() field is changed and source not |
|
|
|