Foam::SolverPerformance<Type> Foam::fvMatrix<Type>::solveSegregated ( const dictionary& solverControls ) { if (debug) { Info.masterStream(this->mesh().comm()) << "fvMatrix<Type>::solveSegregated" "(const dictionary& solverControls) : " "solving fvMatrix<Type>" << endl; } GeometricField<Type, fvPatchField, volMesh>& psi = const_cast<GeometricField<Type, fvPatchField, volMesh>&>(psi_); SolverPerformance<Type> solverPerfVec ( "fvMatrix<Type>::solveSegregated", psi.name() ); scalarField saveDiag(diag()); Field<Type> 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<Type>() ); for (direction cmpt=0; cmpt<Type::nComponents; cmpt++) { if (validComponents[cmpt] == -1) continue; // copy field and source scalarField psiCmpt(psi.internalField().component(cmpt)); addBoundaryDiag(diag(), cmpt); scalarField sourceCmpt(source.component(cmpt)); FieldField<Field, scalar> bouCoeffsCmpt ( boundaryCoeffs_.component(cmpt) ); FieldField<Field, scalar> 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<Type>::componentNames[cmpt], *this, bouCoeffsCmpt, intCoeffsCmpt, interfaces, solverControls )->solve(psiCmpt, sourceCmpt, cmpt); if (SolverPerformance<Type>::debug) { solverPerf.print(Info.masterStream(this->mesh().comm())); } solverPerfVec.replace(cmpt, solverPerf); psi.internalField().replace(cmpt, psiCmpt); diag() = saveDiag; } psi.correctBoundaryConditions(); psi.mesh().setSolverPerformance(psi.name(), solverPerfVec); return solverPerfVec; }
void fvBlockMatrix<Type>::insertDiagSource ( const direction dir, fvMatrix<matrixType>& matrix ) { matrix.completeAssembly(); // Save a copy for different components scalarField& diag = matrix.diag(); scalarField saveDiag(diag); // Add source boundary contribution Field<matrixType>& source = matrix.source(); matrix.addBoundarySource(source, false); const direction nCmpts = pTraits<matrixType>::nComponents; direction localDir = dir; // Get reference to this source field of block system Field<Type>& b = this->source(); if ( // This is needed if the matrixType is <vector>, then you need to grab // coeffs as linear. Consider doing a matrixType check also. // VV, 17/March/2014 this->diag().activeType() != blockCoeffBase::SQUARE ) { typename CoeffField<Type>::linearTypeField& blockDiag = this->diag().asLinear(); for (direction cmptI = 0; cmptI < nCmpts; cmptI++) { matrix.addBoundaryDiag(diag, cmptI); scalarField sourceCmpt(source.component(cmptI)); // FieldField<Field, scalar> bouCoeffsCmpt // ( // matrix.boundaryCoeffs().component(cmptI) // ); // Possible problem for coupled non-aligned boundaries. // VV, 14/May/2014. // matrix.correctImplicitBoundarySource // ( // bouCoeffsCmpt, // sourceCmpt, // cmptI // ); forAll (diag, cellI) { blockDiag[cellI](localDir) = diag[cellI]; b[cellI](localDir) += sourceCmpt[cellI]; } localDir++; // Reset diagonal diag = saveDiag; }