/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. \\/ 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA \*---------------------------------------------------------------------------*/ #include "volFields.H" #include "surfaceFields.H" #include "calculatedFvPatchFields.H" #include "zeroGradientFvPatchFields.H" #include "coupledFvPatchFields.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // template template void Foam::fvMatrix::addToInternalField ( const unallocLabelList& addr, const Field& pf, Field& intf ) const { if (addr.size() != pf.size()) { FatalErrorIn ( "fvMatrix::addToInternalField(const unallocLabelList&, " "const Field&, Field&)" ) << "sizes of addressing and field are different" << abort(FatalError); } forAll(addr, faceI) { intf[addr[faceI]] += pf[faceI]; } } template template void Foam::fvMatrix::addToInternalField ( const unallocLabelList& addr, const tmp >& tpf, Field& intf ) const { addToInternalField(addr, tpf(), intf); tpf.clear(); } template template void Foam::fvMatrix::subtractFromInternalField ( const unallocLabelList& addr, const Field& pf, Field& intf ) const { if (addr.size() != pf.size()) { FatalErrorIn ( "fvMatrix::addToInternalField(const unallocLabelList&, " "const Field&, Field&)" ) << "sizes of addressing and field are different" << abort(FatalError); } forAll(addr, faceI) { intf[addr[faceI]] -= pf[faceI]; } } template template void Foam::fvMatrix::subtractFromInternalField ( const unallocLabelList& addr, const tmp >& tpf, Field& intf ) const { subtractFromInternalField(addr, tpf(), intf); tpf.clear(); } template void Foam::fvMatrix::addBoundaryDiag ( scalarField& diag, const direction solveCmpt ) const { forAll(internalCoeffs_, patchI) { addToInternalField ( lduAddr().patchAddr(patchI), internalCoeffs_[patchI].component(solveCmpt), diag ); } } template void Foam::fvMatrix::addCmptAvBoundaryDiag(scalarField& diag) const { forAll(internalCoeffs_, patchI) { addToInternalField ( lduAddr().patchAddr(patchI), cmptAv(internalCoeffs_[patchI]), diag ); } } template void Foam::fvMatrix::addBoundarySource ( Field& source, const bool couples ) const { forAll(psi_.boundaryField(), patchI) { const fvPatchField& ptf = psi_.boundaryField()[patchI]; const Field& pbc = boundaryCoeffs_[patchI]; if (!ptf.coupled()) { addToInternalField(lduAddr().patchAddr(patchI), pbc, source); } else if (couples) { tmp > tpnf = ptf.patchNeighbourField(); const Field& pnf = tpnf(); const unallocLabelList& addr = lduAddr().patchAddr(patchI); forAll(addr, facei) { source[addr[facei]] += cmptMultiply(pbc[facei], pnf[facei]); } } } } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template Foam::fvMatrix::fvMatrix ( GeometricField& psi, const dimensionSet& ds ) : lduMatrix(psi.mesh()), psi_(psi), dimensions_(ds), source_(psi.size(), pTraits::zero), internalCoeffs_(psi.mesh().boundary().size()), boundaryCoeffs_(psi.mesh().boundary().size()), faceFluxCorrectionPtr_(NULL) { if (debug) { Info<< "fvMatrix(GeometricField&," " const dimensionSet&) : " "constructing fvMatrix for field " << psi_.name() << endl; } // Initialise coupling coefficients forAll (psi.mesh().boundary(), patchI) { internalCoeffs_.set ( patchI, new Field ( psi.mesh().boundary()[patchI].size(), pTraits::zero ) ); boundaryCoeffs_.set ( patchI, new Field ( psi.mesh().boundary()[patchI].size(), pTraits::zero ) ); } psi_.boundaryField().updateCoeffs(); } template Foam::fvMatrix::fvMatrix(const fvMatrix& fvm) : refCount(), lduMatrix(fvm), psi_(fvm.psi_), dimensions_(fvm.dimensions_), source_(fvm.source_), internalCoeffs_(fvm.internalCoeffs_), boundaryCoeffs_(fvm.boundaryCoeffs_), faceFluxCorrectionPtr_(NULL) { if (debug) { Info<< "fvMatrix::fvMatrix(const fvMatrix&) : " << "copying fvMatrix for field " << psi_.name() << endl; } if (fvm.faceFluxCorrectionPtr_) { faceFluxCorrectionPtr_ = new GeometricField ( *(fvm.faceFluxCorrectionPtr_) ); } } #ifdef ConstructFromTmp template Foam::fvMatrix::fvMatrix(const tmp >& tfvm) : refCount(), lduMatrix ( const_cast&>(tfvm()), tfvm.isTmp() ), psi_(tfvm().psi_), dimensions_(tfvm().dimensions_), source_ ( const_cast&>(tfvm()).source_, tfvm.isTmp() ), internalCoeffs_ ( const_cast&>(tfvm()).internalCoeffs_, tfvm.isTmp() ), boundaryCoeffs_ ( const_cast&>(tfvm()).boundaryCoeffs_, tfvm.isTmp() ), faceFluxCorrectionPtr_(NULL) { if (debug) { Info<< "fvMatrix::fvMatrix(const tmp >&) : " << "copying fvMatrix for field " << psi_.name() << endl; } if (tfvm().faceFluxCorrectionPtr_) { if (tfvm.isTmp()) { faceFluxCorrectionPtr_ = tfvm().faceFluxCorrectionPtr_; tfvm().faceFluxCorrectionPtr_ = NULL; } else { faceFluxCorrectionPtr_ = new GeometricField ( *(tfvm().faceFluxCorrectionPtr_) ); } } tfvm.clear(); } #endif template Foam::fvMatrix::fvMatrix ( GeometricField& psi, Istream& is ) : lduMatrix(psi.mesh()), psi_(psi), dimensions_(is), source_(is), internalCoeffs_(psi.mesh().boundary().size()), boundaryCoeffs_(psi.mesh().boundary().size()), faceFluxCorrectionPtr_(NULL) { if (debug) { Info<< "fvMatrix" "(GeometricField&, Istream&) : " "constructing fvMatrix for field " << psi_.name() << endl; } // Initialise coupling coefficients forAll (psi.mesh().boundary(), patchI) { internalCoeffs_.set ( patchI, new Field ( psi.mesh().boundary()[patchI].size(), pTraits::zero ) ); boundaryCoeffs_.set ( patchI, new Field ( psi.mesh().boundary()[patchI].size(), pTraits::zero ) ); } } template Foam::fvMatrix::~fvMatrix() { if (debug) { Info<< "fvMatrix::~fvMatrix() : " << "destroying fvMatrix for field " << psi_.name() << endl; } if (faceFluxCorrectionPtr_) { delete faceFluxCorrectionPtr_; } } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // Set solution in given cells and eliminate corresponding // equations from the matrix template void Foam::fvMatrix::setValues ( const labelList& cellLabels, const Field& values ) { const fvMesh& mesh = psi_.mesh(); const cellList& cells = mesh.cells(); const unallocLabelList& own = mesh.owner(); const unallocLabelList& nei = mesh.neighbour(); scalarField& Diag = diag(); forAll(cellLabels, i) { label celli = cellLabels[i]; psi_[celli] = values[i]; source_[celli] = values[i]*Diag[celli]; if (symmetric() || asymmetric()) { const cell& c = cells[celli]; forAll(c, j) { label facei = c[j]; if (mesh.isInternalFace(facei)) { if (symmetric()) { if (celli == own[facei]) { source_[nei[facei]] -= upper()[facei]*values[i]; } else { source_[own[facei]] -= upper()[facei]*values[i]; } upper()[facei] = 0.0; } else { if (celli == own[facei]) { source_[nei[facei]] -= lower()[facei]*values[i]; } else { source_[own[facei]] -= upper()[facei]*values[i]; } upper()[facei] = 0.0; lower()[facei] = 0.0; } } else { label patchi = mesh.boundaryMesh().whichPatch(facei); if (internalCoeffs_[patchi].size()) { label patchFacei = mesh.boundaryMesh()[patchi].whichFace(facei); internalCoeffs_[patchi][patchFacei] = pTraits::zero; boundaryCoeffs_[patchi][patchFacei] = pTraits::zero; } } } } } } // Set reference level for solution template void Foam::fvMatrix::setReference ( const label cell, const Type& value, const bool forceReference ) { if (psi_.needReference() || forceReference) { if (cell >= 0) { source()[cell] += diag()[cell]*value; diag()[cell] += diag()[cell]; } } } template void Foam::fvMatrix::relax(const scalar alpha) { if (alpha <= 0) { return; } Field& 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& ptf = psi_.boundaryField()[patchI]; if (ptf.size()) { const unallocLabelList& pa = lduAddr().patchAddr(patchI); Field& iCoeffs = internalCoeffs_[patchI]; if (ptf.coupled()) { const Field& 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]]); } } } } // Ensure the matrix is diagonally dominant... max(D, D, sumOff); // ... then relax D /= alpha; // Now remove the diagonal contribution from coupled boundaries forAll(psi_.boundaryField(), patchI) { const fvPatchField& ptf = psi_.boundaryField()[patchI]; if (ptf.size()) { const unallocLabelList& pa = lduAddr().patchAddr(patchI); Field& iCoeffs = internalCoeffs_[patchI]; if (ptf.coupled()) { forAll(pa, face) { D[pa[face]] -= component(iCoeffs[face], 0); } } } } // Finally add the relaxation contribution to the source. S += (D - D0)*psi_.internalField(); } template void Foam::fvMatrix::relax() { if (psi_.mesh().relax(psi_.name())) { relax(psi_.mesh().relaxationFactor(psi_.name())); } } template void Foam::fvMatrix::boundaryManipulate ( typename GeometricField:: GeometricBoundaryField& bFields ) { forAll(bFields, patchI) { bFields[patchI].manipulateMatrix(*this); } } template Foam::tmp Foam::fvMatrix::D() const { tmp tdiag(new scalarField(diag())); addCmptAvBoundaryDiag(tdiag()); return tdiag; } template Foam::tmp > Foam::fvMatrix::DD() const { tmp > tdiag(pTraits::one*diag()); forAll(psi_.boundaryField(), patchI) { const fvPatchField& ptf = psi_.boundaryField()[patchI]; if (!ptf.coupled() && ptf.size()) { addToInternalField ( lduAddr().patchAddr(patchI), internalCoeffs_[patchI], tdiag() ); } } return tdiag; } template Foam::tmp Foam::fvMatrix::A() const { tmp tAphi ( new volScalarField ( IOobject ( "A("+psi_.name()+')', psi_.instance(), psi_.mesh(), IOobject::NO_READ, IOobject::NO_WRITE ), psi_.mesh(), dimensions_/psi_.dimensions()/dimVol, zeroGradientFvPatchScalarField::typeName ) ); tAphi().internalField() = D()/psi_.mesh().V(); tAphi().correctBoundaryConditions(); return tAphi; } template Foam::tmp > Foam::fvMatrix::H() const { tmp > tHphi ( new GeometricField ( IOobject ( "H("+psi_.name()+')', psi_.instance(), psi_.mesh(), IOobject::NO_READ, IOobject::NO_WRITE ), psi_.mesh(), dimensions_/dimVol, zeroGradientFvPatchScalarField::typeName ) ); GeometricField& Hphi = tHphi(); // Loop over field components for (direction cmpt=0; cmpt, Type::rank>::type>::zero ) ); for(direction cmpt=0; cmpt Foam::tmp Foam::fvMatrix::H1() const { tmp tH1 ( new volScalarField ( IOobject ( "H(1)", psi_.instance(), psi_.mesh(), IOobject::NO_READ, IOobject::NO_WRITE ), psi_.mesh(), dimensions_/(dimVol*psi_.dimensions()), zeroGradientFvPatchScalarField::typeName ) ); volScalarField& H1_ = tH1(); // Loop over field components /* for (direction cmpt=0; cmpt Foam::tmp > Foam::fvMatrix:: flux() const { if (!psi_.mesh().fluxRequired(psi_.name())) { FatalErrorIn("fvMatrix::flux()") << "flux requested but " << psi_.name() << " not specified in the fluxRequired sub-dictionary" " of fvSchemes." << abort(FatalError); } // construct GeometricField tmp > tfieldFlux ( new GeometricField ( IOobject ( "flux("+psi_.name()+')', psi_.instance(), psi_.mesh(), IOobject::NO_READ, IOobject::NO_WRITE ), psi_.mesh(), dimensions() ) ); GeometricField& fieldFlux = tfieldFlux(); for (direction cmpt=0; cmpt::nComponents; cmpt++) { fieldFlux.internalField().replace ( cmpt, lduMatrix::faceH(psi_.internalField().component(cmpt)) ); } FieldField InternalContrib = internalCoeffs_; forAll(InternalContrib, patchI) { InternalContrib[patchI] = cmptMultiply ( InternalContrib[patchI], psi_.boundaryField()[patchI].patchInternalField() ); } FieldField NeighbourContrib = boundaryCoeffs_; forAll(NeighbourContrib, patchI) { if (psi_.boundaryField()[patchI].coupled()) { NeighbourContrib[patchI] = cmptMultiply ( NeighbourContrib[patchI], psi_.boundaryField()[patchI].patchNeighbourField() ); } } forAll(fieldFlux.boundaryField(), patchI) { fieldFlux.boundaryField()[patchI] = InternalContrib[patchI] - NeighbourContrib[patchI]; } if (faceFluxCorrectionPtr_) { fieldFlux += *faceFluxCorrectionPtr_; } return tfieldFlux; } // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template void Foam::fvMatrix::operator=(const fvMatrix& fvmv) { if (this == &fvmv) { FatalErrorIn("fvMatrix::operator=(const fvMatrix&)") << "attempted assignment to self" << abort(FatalError); } if (&psi_ != &(fvmv.psi_)) { FatalErrorIn("fvMatrix::operator=(const fvMatrix&)") << "different fields" << abort(FatalError); } lduMatrix::operator=(fvmv); source_ = fvmv.source_; internalCoeffs_ = fvmv.internalCoeffs_; boundaryCoeffs_ = fvmv.boundaryCoeffs_; if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_) { *faceFluxCorrectionPtr_ = *fvmv.faceFluxCorrectionPtr_; } else if (fvmv.faceFluxCorrectionPtr_) { faceFluxCorrectionPtr_ = new GeometricField (*fvmv.faceFluxCorrectionPtr_); } } template void Foam::fvMatrix::operator=(const tmp >& tfvmv) { operator=(tfvmv()); tfvmv.clear(); } template void Foam::fvMatrix::negate() { lduMatrix::negate(); source_.negate(); internalCoeffs_.negate(); boundaryCoeffs_.negate(); if (faceFluxCorrectionPtr_) { faceFluxCorrectionPtr_->negate(); } } template void Foam::fvMatrix::operator+=(const fvMatrix& fvmv) { checkMethod(*this, fvmv, "+="); dimensions_ += fvmv.dimensions_; lduMatrix::operator+=(fvmv); source_ += fvmv.source_; internalCoeffs_ += fvmv.internalCoeffs_; boundaryCoeffs_ += fvmv.boundaryCoeffs_; if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_) { *faceFluxCorrectionPtr_ += *fvmv.faceFluxCorrectionPtr_; } else if (fvmv.faceFluxCorrectionPtr_) { faceFluxCorrectionPtr_ = new GeometricField ( *fvmv.faceFluxCorrectionPtr_ ); } } template void Foam::fvMatrix::operator+=(const tmp >& tfvmv) { operator+=(tfvmv()); tfvmv.clear(); } template void Foam::fvMatrix::operator-=(const fvMatrix& fvmv) { checkMethod(*this, fvmv, "+="); dimensions_ -= fvmv.dimensions_; lduMatrix::operator-=(fvmv); source_ -= fvmv.source_; internalCoeffs_ -= fvmv.internalCoeffs_; boundaryCoeffs_ -= fvmv.boundaryCoeffs_; if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_) { *faceFluxCorrectionPtr_ -= *fvmv.faceFluxCorrectionPtr_; } else if (fvmv.faceFluxCorrectionPtr_) { faceFluxCorrectionPtr_ = new GeometricField (-*fvmv.faceFluxCorrectionPtr_); } } template void Foam::fvMatrix::operator-=(const tmp >& tfvmv) { operator-=(tfvmv()); tfvmv.clear(); } template void Foam::fvMatrix::operator+= ( const DimensionedField& su ) { checkMethod(*this, su, "+="); source() -= su.mesh().V()*su.field(); } template void Foam::fvMatrix::operator+= ( const tmp >& tsu ) { operator+=(tsu()); tsu.clear(); } template void Foam::fvMatrix::operator+= ( const tmp >& tsu ) { operator+=(tsu()); tsu.clear(); } template void Foam::fvMatrix::operator-= ( const DimensionedField& su ) { checkMethod(*this, su, "-="); source() += su.mesh().V()*su.field(); } template void Foam::fvMatrix::operator-= ( const tmp >& tsu ) { operator-=(tsu()); tsu.clear(); } template void Foam::fvMatrix::operator-= ( const tmp >& tsu ) { operator-=(tsu()); tsu.clear(); } template void Foam::fvMatrix::operator+= ( const dimensioned& su ) { source() -= psi().mesh().V()*su; } template void Foam::fvMatrix::operator-= ( const dimensioned& su ) { source() += psi().mesh().V()*su; } template void Foam::fvMatrix::operator+= ( const zeroField& ) {} template void Foam::fvMatrix::operator-= ( const zeroField& ) {} template void Foam::fvMatrix::operator*= ( const DimensionedField& dsf ) { dimensions_ *= dsf.dimensions(); lduMatrix::operator*=(dsf.field()); source_ *= dsf.field(); forAll(boundaryCoeffs_, patchI) { scalarField psf ( dsf.mesh().boundary()[patchI].patchInternalField(dsf.field()) ); internalCoeffs_[patchI] *= psf; boundaryCoeffs_[patchI] *= psf; } if (faceFluxCorrectionPtr_) { FatalErrorIn ( "fvMatrix::operator*=" "(const DimensionedField&)" ) << "cannot scale a matrix containing a faceFluxCorrection" << abort(FatalError); } } template void Foam::fvMatrix::operator*= ( const tmp >& tdsf ) { operator*=(tdsf()); tdsf.clear(); } template void Foam::fvMatrix::operator*= ( const tmp& tvsf ) { operator*=(tvsf()); tvsf.clear(); } template void Foam::fvMatrix::operator*= ( const dimensioned& ds ) { dimensions_ *= ds.dimensions(); lduMatrix::operator*=(ds.value()); source_ *= ds.value(); internalCoeffs_ *= ds.value(); boundaryCoeffs_ *= ds.value(); if (faceFluxCorrectionPtr_) { *faceFluxCorrectionPtr_ *= ds.value(); } } // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * // template void Foam::checkMethod ( const fvMatrix& fvm1, const fvMatrix& fvm2, const char* op ) { if (&fvm1.psi() != &fvm2.psi()) { FatalErrorIn ( "checkMethod(const fvMatrix&, const fvMatrix&)" ) << "incompatible fields for operation " << endl << " " << "[" << fvm1.psi().name() << "] " << op << " [" << fvm2.psi().name() << "]" << abort(FatalError); } if (dimensionSet::debug && fvm1.dimensions() != fvm2.dimensions()) { FatalErrorIn ( "checkMethod(const fvMatrix&, const fvMatrix&)" ) << "incompatible dimensions for operation " << endl << " " << "[" << fvm1.psi().name() << fvm1.dimensions()/dimVolume << " ] " << op << " [" << fvm2.psi().name() << fvm2.dimensions()/dimVolume << " ]" << abort(FatalError); } } template void Foam::checkMethod ( const fvMatrix& fvm, const DimensionedField& df, const char* op ) { if (dimensionSet::debug && fvm.dimensions()/dimVolume != df.dimensions()) { FatalErrorIn ( "checkMethod(const fvMatrix&, const GeometricField&)" ) << "incompatible dimensions for operation " << endl << " " << "[" << fvm.psi().name() << fvm.dimensions()/dimVolume << " ] " << op << " [" << df.name() << df.dimensions() << " ]" << abort(FatalError); } } template void Foam::checkMethod ( const fvMatrix& fvm, const dimensioned& dt, const char* op ) { if (dimensionSet::debug && fvm.dimensions()/dimVolume != dt.dimensions()) { FatalErrorIn ( "checkMethod(const fvMatrix&, const dimensioned&)" ) << "incompatible dimensions for operation " << endl << " " << "[" << fvm.psi().name() << fvm.dimensions()/dimVolume << " ] " << op << " [" << dt.name() << dt.dimensions() << " ]" << abort(FatalError); } } template Foam::lduMatrix::solverPerformance Foam::solve ( fvMatrix& fvm, const dictionary& solverControls ) { return fvm.solve(solverControls); } template Foam::lduMatrix::solverPerformance Foam::solve ( const tmp >& tfvm, const dictionary& solverControls ) { lduMatrix::solverPerformance solverPerf = const_cast&>(tfvm()).solve(solverControls); tfvm.clear(); return solverPerf; } template Foam::lduMatrix::solverPerformance Foam::solve(fvMatrix& fvm) { return fvm.solve(); } template Foam::lduMatrix::solverPerformance Foam::solve(const tmp >& tfvm) { lduMatrix::solverPerformance solverPerf = const_cast&>(tfvm()).solve(); tfvm.clear(); return solverPerf; } // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // template Foam::tmp > Foam::operator== ( const fvMatrix& A, const fvMatrix& B ) { checkMethod(A, B, "=="); return (A - B); } template Foam::tmp > Foam::operator== ( const tmp >& tA, const fvMatrix& B ) { checkMethod(tA(), B, "=="); return (tA - B); } template Foam::tmp > Foam::operator== ( const fvMatrix& A, const tmp >& tB ) { checkMethod(A, tB(), "=="); return (A - tB); } template Foam::tmp > Foam::operator== ( const tmp >& tA, const tmp >& tB ) { checkMethod(tA(), tB(), "=="); return (tA - tB); } template Foam::tmp > Foam::operator== ( const fvMatrix& A, const DimensionedField& su ) { checkMethod(A, su, "=="); tmp > tC(new fvMatrix(A)); tC().source() += su.mesh().V()*su.field(); return tC; } template Foam::tmp > Foam::operator== ( const fvMatrix& A, const tmp >& tsu ) { checkMethod(A, tsu(), "=="); tmp > tC(new fvMatrix(A)); tC().source() += tsu().mesh().V()*tsu().field(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator== ( const fvMatrix& A, const tmp >& tsu ) { checkMethod(A, tsu(), "=="); tmp > tC(new fvMatrix(A)); tC().source() += tsu().mesh().V()*tsu().internalField(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator== ( const tmp >& tA, const DimensionedField& su ) { checkMethod(tA(), su, "=="); tmp > tC(tA.ptr()); tC().source() += su.mesh().V()*su.field(); return tC; } template Foam::tmp > Foam::operator== ( const tmp >& tA, const tmp >& tsu ) { checkMethod(tA(), tsu(), "=="); tmp > tC(tA.ptr()); tC().source() += tsu().mesh().V()*tsu().field(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator== ( const tmp >& tA, const tmp >& tsu ) { checkMethod(tA(), tsu(), "=="); tmp > tC(tA.ptr()); tC().source() += tsu().mesh().V()*tsu().internalField(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator== ( const fvMatrix& A, const dimensioned& su ) { checkMethod(A, su, "=="); tmp > tC(new fvMatrix(A)); tC().source() += A.psi().mesh().V()*su.value(); return tC; } template Foam::tmp > Foam::operator== ( const tmp >& tA, const dimensioned& su ) { checkMethod(tA(), su, "=="); tmp > tC(tA.ptr()); tC().source() += tC().psi().mesh().V()*su.value(); return tC; } template Foam::tmp > Foam::operator== ( const fvMatrix& A, const zeroField& ) { return A; } template Foam::tmp > Foam::operator== ( const tmp >& tA, const zeroField& ) { return tA; } template Foam::tmp > Foam::operator- ( const fvMatrix& A ) { tmp > tC(new fvMatrix(A)); tC().negate(); return tC; } template Foam::tmp > Foam::operator- ( const tmp >& tA ) { tmp > tC(tA.ptr()); tC().negate(); return tC; } template Foam::tmp > Foam::operator+ ( const fvMatrix& A, const fvMatrix& B ) { checkMethod(A, B, "+"); tmp > tC(new fvMatrix(A)); tC() += B; return tC; } template Foam::tmp > Foam::operator+ ( const tmp >& tA, const fvMatrix& B ) { checkMethod(tA(), B, "+"); tmp > tC(tA.ptr()); tC() += B; return tC; } template Foam::tmp > Foam::operator+ ( const fvMatrix& A, const tmp >& tB ) { checkMethod(A, tB(), "+"); tmp > tC(tB.ptr()); tC() += A; return tC; } template Foam::tmp > Foam::operator+ ( const tmp >& tA, const tmp >& tB ) { checkMethod(tA(), tB(), "+"); tmp > tC(tA.ptr()); tC() += tB(); tB.clear(); return tC; } template Foam::tmp > Foam::operator+ ( const fvMatrix& A, const DimensionedField& su ) { checkMethod(A, su, "+"); tmp > tC(new fvMatrix(A)); tC().source() -= su.mesh().V()*su.field(); return tC; } template Foam::tmp > Foam::operator+ ( const fvMatrix& A, const tmp >& tsu ) { checkMethod(A, tsu(), "+"); tmp > tC(new fvMatrix(A)); tC().source() -= tsu().mesh().V()*tsu().field(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator+ ( const fvMatrix& A, const tmp >& tsu ) { checkMethod(A, tsu(), "+"); tmp > tC(new fvMatrix(A)); tC().source() -= tsu().mesh().V()*tsu().internalField(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator+ ( const tmp >& tA, const DimensionedField& su ) { checkMethod(tA(), su, "+"); tmp > tC(tA.ptr()); tC().source() -= su.mesh().V()*su.field(); return tC; } template Foam::tmp > Foam::operator+ ( const tmp >& tA, const tmp >& tsu ) { checkMethod(tA(), tsu(), "+"); tmp > tC(tA.ptr()); tC().source() -= tsu().mesh().V()*tsu().field(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator+ ( const tmp >& tA, const tmp >& tsu ) { checkMethod(tA(), tsu(), "+"); tmp > tC(tA.ptr()); tC().source() -= tsu().mesh().V()*tsu().internalField(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator+ ( const DimensionedField& su, const fvMatrix& A ) { checkMethod(A, su, "+"); tmp > tC(new fvMatrix(A)); tC().source() -= su.mesh().V()*su.field(); return tC; } template Foam::tmp > Foam::operator+ ( const tmp >& tsu, const fvMatrix& A ) { checkMethod(A, tsu(), "+"); tmp > tC(new fvMatrix(A)); tC().source() -= tsu().mesh().V()*tsu().field(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator+ ( const tmp >& tsu, const fvMatrix& A ) { checkMethod(A, tsu(), "+"); tmp > tC(new fvMatrix(A)); tC().source() -= tsu().mesh().V()*tsu().internalField(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator+ ( const DimensionedField& su, const tmp >& tA ) { checkMethod(tA(), su, "+"); tmp > tC(tA.ptr()); tC().source() -= su.mesh().V()*su.field(); return tC; } template Foam::tmp > Foam::operator+ ( const tmp >& tsu, const tmp >& tA ) { checkMethod(tA(), tsu(), "+"); tmp > tC(tA.ptr()); tC().source() -= tsu().mesh().V()*tsu().field(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator+ ( const tmp >& tsu, const tmp >& tA ) { checkMethod(tA(), tsu(), "+"); tmp > tC(tA.ptr()); tC().source() -= tsu().mesh().V()*tsu().internalField(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator- ( const fvMatrix& A, const fvMatrix& B ) { checkMethod(A, B, "-"); tmp > tC(new fvMatrix(A)); tC() -= B; return tC; } template Foam::tmp > Foam::operator- ( const tmp >& tA, const fvMatrix& B ) { checkMethod(tA(), B, "-"); tmp > tC(tA.ptr()); tC() -= B; return tC; } template Foam::tmp > Foam::operator- ( const fvMatrix& A, const tmp >& tB ) { checkMethod(A, tB(), "-"); tmp > tC(tB.ptr()); tC() -= A; tC().negate(); return tC; } template Foam::tmp > Foam::operator- ( const tmp >& tA, const tmp >& tB ) { checkMethod(tA(), tB(), "-"); tmp > tC(tA.ptr()); tC() -= tB(); tB.clear(); return tC; } template Foam::tmp > Foam::operator- ( const fvMatrix& A, const DimensionedField& su ) { checkMethod(A, su, "-"); tmp > tC(new fvMatrix(A)); tC().source() += su.mesh().V()*su.field(); return tC; } template Foam::tmp > Foam::operator- ( const fvMatrix& A, const tmp >& tsu ) { checkMethod(A, tsu(), "-"); tmp > tC(new fvMatrix(A)); tC().source() += tsu().mesh().V()*tsu().field(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator- ( const fvMatrix& A, const tmp >& tsu ) { checkMethod(A, tsu(), "-"); tmp > tC(new fvMatrix(A)); tC().source() += tsu().mesh().V()*tsu().internalField(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator- ( const tmp >& tA, const DimensionedField& su ) { checkMethod(tA(), su, "-"); tmp > tC(tA.ptr()); tC().source() += su.mesh().V()*su.field(); return tC; } template Foam::tmp > Foam::operator- ( const tmp >& tA, const tmp >& tsu ) { checkMethod(tA(), tsu(), "-"); tmp > tC(tA.ptr()); tC().source() += tsu().mesh().V()*tsu().field(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator- ( const tmp >& tA, const tmp >& tsu ) { checkMethod(tA(), tsu(), "-"); tmp > tC(tA.ptr()); tC().source() += tsu().mesh().V()*tsu().internalField(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator- ( const DimensionedField& su, const fvMatrix& A ) { checkMethod(A, su, "-"); tmp > tC(new fvMatrix(A)); tC().negate(); tC().source() -= su.mesh().V()*su.field(); return tC; } template Foam::tmp > Foam::operator- ( const tmp >& tsu, const fvMatrix& A ) { checkMethod(A, tsu(), "-"); tmp > tC(new fvMatrix(A)); tC().negate(); tC().source() -= tsu().mesh().V()*tsu().field(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator- ( const tmp >& tsu, const fvMatrix& A ) { checkMethod(A, tsu(), "-"); tmp > tC(new fvMatrix(A)); tC().negate(); tC().source() -= tsu().mesh().V()*tsu().internalField(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator- ( const DimensionedField& su, const tmp >& tA ) { checkMethod(tA(), su, "-"); tmp > tC(tA.ptr()); tC().negate(); tC().source() -= su.mesh().V()*su.field(); return tC; } template Foam::tmp > Foam::operator- ( const tmp >& tsu, const tmp >& tA ) { checkMethod(tA(), tsu(), "-"); tmp > tC(tA.ptr()); tC().negate(); tC().source() -= tsu().mesh().V()*tsu().field(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator- ( const tmp >& tsu, const tmp >& tA ) { checkMethod(tA(), tsu(), "-"); tmp > tC(tA.ptr()); tC().negate(); tC().source() -= tsu().mesh().V()*tsu().internalField(); tsu.clear(); return tC; } template Foam::tmp > Foam::operator+ ( const fvMatrix& A, const dimensioned& su ) { checkMethod(A, su, "+"); tmp > tC(new fvMatrix(A)); tC().source() -= su.value()*A.psi().mesh().V(); return tC; } template Foam::tmp > Foam::operator+ ( const tmp >& tA, const dimensioned& su ) { checkMethod(tA(), su, "+"); tmp > tC(tA.ptr()); tC().source() -= su.value()*tC().psi().mesh().V(); return tC; } template Foam::tmp > Foam::operator+ ( const dimensioned& su, const fvMatrix& A ) { checkMethod(A, su, "+"); tmp > tC(new fvMatrix(A)); tC().source() -= su.value()*A.psi().mesh().V(); return tC; } template Foam::tmp > Foam::operator+ ( const dimensioned& su, const tmp >& tA ) { checkMethod(tA(), su, "+"); tmp > tC(tA.ptr()); tC().source() -= su.value()*tC().psi().mesh().V(); return tC; } template Foam::tmp > Foam::operator- ( const fvMatrix& A, const dimensioned& su ) { checkMethod(A, su, "-"); tmp > tC(new fvMatrix(A)); tC().source() += su.value()*tC().psi().mesh().V(); return tC; } template Foam::tmp > Foam::operator- ( const tmp >& tA, const dimensioned& su ) { checkMethod(tA(), su, "-"); tmp > tC(tA.ptr()); tC().source() += su.value()*tC().psi().mesh().V(); return tC; } template Foam::tmp > Foam::operator- ( const dimensioned& su, const fvMatrix& A ) { checkMethod(A, su, "-"); tmp > tC(new fvMatrix(A)); tC().negate(); tC().source() -= su.value()*A.psi().mesh().V(); return tC; } template Foam::tmp > Foam::operator- ( const dimensioned& su, const tmp >& tA ) { checkMethod(tA(), su, "-"); tmp > tC(tA.ptr()); tC().negate(); tC().source() -= su.value()*tC().psi().mesh().V(); return tC; } template Foam::tmp > Foam::operator* ( const DimensionedField& dsf, const fvMatrix& A ) { tmp > tC(new fvMatrix(A)); tC() *= dsf; return tC; } template Foam::tmp > Foam::operator* ( const tmp< DimensionedField >& tdsf, const fvMatrix& A ) { tmp > tC(new fvMatrix(A)); tC() *= tdsf; return tC; } template Foam::tmp > Foam::operator* ( const tmp& tvsf, const fvMatrix& A ) { tmp > tC(new fvMatrix(A)); tC() *= tvsf; return tC; } template Foam::tmp > Foam::operator* ( const DimensionedField& dsf, const tmp >& tA ) { tmp > tC(tA.ptr()); tC() *= dsf; return tC; } template Foam::tmp > Foam::operator* ( const tmp >& tdsf, const tmp >& tA ) { tmp > tC(tA.ptr()); tC() *= tdsf; return tC; } template Foam::tmp > Foam::operator* ( const tmp& tvsf, const tmp >& tA ) { tmp > tC(tA.ptr()); tC() *= tvsf; return tC; } template Foam::tmp > Foam::operator* ( const dimensioned& ds, const fvMatrix& A ) { tmp > tC(new fvMatrix(A)); tC() *= ds; return tC; } template Foam::tmp > Foam::operator* ( const dimensioned& ds, const tmp >& tA ) { tmp > tC(tA.ptr()); tC() *= ds; return tC; } template Foam::tmp > Foam::operator& ( const fvMatrix& M, const DimensionedField& psi ) { tmp > tMphi ( new GeometricField ( IOobject ( "M&" + psi.name(), psi.instance(), psi.mesh(), IOobject::NO_READ, IOobject::NO_WRITE ), psi.mesh(), M.dimensions()/dimVol, zeroGradientFvPatchScalarField::typeName ) ); GeometricField& Mphi = tMphi(); // Loop over field components for (direction cmpt=0; cmpt::nComponents; cmpt++) { scalarField psiCmpt = psi.field().component(cmpt); scalarField boundaryDiagCmpt(M.diag()); M.addBoundaryDiag(boundaryDiagCmpt, cmpt); Mphi.internalField().replace(cmpt, -boundaryDiagCmpt*psiCmpt); } Mphi.internalField() += M.lduMatrix::H(psi.field()) + M.source(); M.addBoundarySource(Mphi.internalField()); Mphi.internalField() /= -psi.mesh().V(); Mphi.correctBoundaryConditions(); return tMphi; } template Foam::tmp > Foam::operator& ( const fvMatrix& M, const tmp >& tpsi ) { tmp > tMpsi = M & tpsi(); tpsi.clear(); return tMpsi; } template Foam::tmp > Foam::operator& ( const fvMatrix& M, const tmp >& tpsi ) { tmp > tMpsi = M & tpsi(); tpsi.clear(); return tMpsi; } template Foam::tmp > Foam::operator& ( const tmp >& tM, const DimensionedField& psi ) { tmp > tMpsi = tM() & psi; tM.clear(); return tMpsi; } template Foam::tmp > Foam::operator& ( const tmp >& tM, const tmp >& tpsi ) { tmp > tMpsi = tM() & tpsi(); tM.clear(); tpsi.clear(); return tMpsi; } template Foam::tmp > Foam::operator& ( const tmp >& tM, const tmp >& tpsi ) { tmp > tMpsi = tM() & tpsi(); tM.clear(); tpsi.clear(); return tMpsi; } // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // template Foam::Ostream& Foam::operator<<(Ostream& os, const fvMatrix& fvm) { os << static_cast(fvm) << nl << fvm.dimensions_ << nl << fvm.source_ << nl << fvm.internalCoeffs_ << nl << fvm.boundaryCoeffs_ << endl; os.check("Ostream& operator<<(Ostream&, fvMatrix&"); return os; } // * * * * * * * * * * * * * * * * Solvers * * * * * * * * * * * * * * * * * // #include "fvMatrixSolve.C" // ************************************************************************* //