/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-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 . \*---------------------------------------------------------------------------*/ #include "LduMatrix.H" #include "diagTensorField.H" // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template void Foam::fvMatrix::setComponentReference ( const label patchi, const label facei, const direction cmpt, const scalar value ) { if (psi_.needReference()) { if (Pstream::master()) { internalCoeffs_[patchi][facei].component(cmpt) += diag()[psi_.mesh().boundary()[patchi].faceCells()[facei]]; boundaryCoeffs_[patchi][facei].component(cmpt) += diag()[psi_.mesh().boundary()[patchi].faceCells()[facei]] *value; } } } template Foam::SolverPerformance Foam::fvMatrix::solve ( const dictionary& solverControls ) { if (debug) { Info.masterStream(this->mesh().comm()) << "fvMatrix::solve(const dictionary& solverControls) : " "solving fvMatrix" << endl; } label maxIter = -1; if (solverControls.readIfPresent("maxIter", maxIter)) { if (maxIter == 0) { return SolverPerformance(); } } word type(solverControls.lookupOrDefault("type", "segregated")); if (type == "segregated") { return solveSegregated(solverControls); } else if (type == "coupled") { return solveCoupled(solverControls); } else { FatalIOErrorInFunction ( solverControls ) << "Unknown type " << type << "; currently supported solver types are segregated and coupled" << exit(FatalIOError); return SolverPerformance(); } } template Foam::SolverPerformance Foam::fvMatrix::solveSegregated ( const dictionary& solverControls ) { if (debug) { Info.masterStream(this->mesh().comm()) << "fvMatrix::solveSegregated" "(const dictionary& solverControls) : " "solving fvMatrix" << endl; } GeometricField& psi = const_cast&>(psi_); SolverPerformance solverPerfVec ( "fvMatrix::solveSegregated", psi.name() ); scalarField saveDiag(diag()); Field source(source_); // At this point include the boundary source from the coupled boundaries. // This is corrected for the implict part by updateMatrixInterfaces within // the component loop. addBoundarySource(source); typename Type::labelType validComponents ( psi.mesh().template validComponents() ); for (direction cmpt=0; cmpt bouCoeffsCmpt ( boundaryCoeffs_.component(cmpt) ); FieldField intCoeffsCmpt ( internalCoeffs_.component(cmpt) ); lduInterfaceFieldPtrsList interfaces = psi.boundaryField().scalarInterfaces(); // Use the initMatrixInterfaces and updateMatrixInterfaces to correct // bouCoeffsCmpt for the explicit part of the coupled boundary // conditions initMatrixInterfaces ( bouCoeffsCmpt, interfaces, psiCmpt, sourceCmpt, cmpt ); updateMatrixInterfaces ( bouCoeffsCmpt, interfaces, psiCmpt, sourceCmpt, cmpt ); solverPerformance solverPerf; // Solver call solverPerf = lduMatrix::solver::New ( psi.name() + pTraits::componentNames[cmpt], *this, bouCoeffsCmpt, intCoeffsCmpt, interfaces, solverControls )->solve(psiCmpt, sourceCmpt, cmpt); if (SolverPerformance::debug) { solverPerf.print(Info.masterStream(this->mesh().comm())); } solverPerfVec.replace(cmpt, solverPerf); psi.internalFieldRef().replace(cmpt, psiCmpt); diag() = saveDiag; } psi.correctBoundaryConditions(); psi.mesh().setSolverPerformance(psi.name(), solverPerfVec); return solverPerfVec; } template Foam::SolverPerformance Foam::fvMatrix::solveCoupled ( const dictionary& solverControls ) { if (debug) { Info.masterStream(this->mesh().comm()) << "fvMatrix::solveCoupled" "(const dictionary& solverControls) : " "solving fvMatrix" << endl; } GeometricField& psi = const_cast&>(psi_); LduMatrix coupledMatrix(psi.mesh()); coupledMatrix.diag() = diag(); coupledMatrix.upper() = upper(); coupledMatrix.lower() = lower(); coupledMatrix.source() = source(); addBoundaryDiag(coupledMatrix.diag(), 0); addBoundarySource(coupledMatrix.source(), false); coupledMatrix.interfaces() = psi.boundaryFieldRef().interfaces(); coupledMatrix.interfacesUpper() = boundaryCoeffs().component(0); coupledMatrix.interfacesLower() = internalCoeffs().component(0); autoPtr::solver> coupledMatrixSolver ( LduMatrix::solver::New ( psi.name(), coupledMatrix, solverControls ) ); SolverPerformance solverPerf ( coupledMatrixSolver->solve(psi) ); if (SolverPerformance::debug) { solverPerf.print(Info.masterStream(this->mesh().comm())); } psi.correctBoundaryConditions(); psi.mesh().setSolverPerformance(psi.name(), solverPerf); return solverPerf; } template Foam::autoPtr::fvSolver> Foam::fvMatrix::solver() { return solver ( psi_.mesh().solverDict ( psi_.select ( psi_.mesh().data::template lookupOrDefault ("finalIteration", false) ) ) ); } template Foam::SolverPerformance Foam::fvMatrix::fvSolver::solve() { return solve ( fvMat_.psi_.mesh().solverDict ( fvMat_.psi_.select ( fvMat_.psi_.mesh().data::template lookupOrDefault ("finalIteration", false) ) ) ); } template Foam::SolverPerformance Foam::fvMatrix::solve() { return solve ( psi_.mesh().solverDict ( psi_.select ( psi_.mesh().data::template lookupOrDefault ("finalIteration", false) ) ) ); } template Foam::tmp> Foam::fvMatrix::residual() const { tmp> tres(new Field(source_)); Field& res = tres(); addBoundarySource(res); // Loop over field components for (direction cmpt=0; cmpt bouCoeffsCmpt ( boundaryCoeffs_.component(cmpt) ); res.replace ( cmpt, lduMatrix::residual ( psiCmpt, res.component(cmpt) - boundaryDiagCmpt*psiCmpt, bouCoeffsCmpt, psi_.boundaryField().scalarInterfaces(), cmpt ) ); } return tres; } // ************************************************************************* //