void Foam::coupledLduMatrix::Amul ( FieldField<Field, scalar>& result, const FieldField<Field, scalar>& x, const PtrList<FieldField<Field, scalar> >& bouCoeffs, const lduInterfaceFieldPtrsListList& interfaces, const direction cmpt ) const { const PtrList<lduMatrix>& matrices = *this; // Reset product to zero result = 0; // Initialise the update of coupled interfaces initMatrixInterfaces ( bouCoeffs, interfaces, x, result, cmpt ); forAll (matrices, rowI) { matrices[rowI].AmulCore(result[rowI], x[rowI]); }
void Foam::lduMatrix::Amul ( scalarField& Apsi, const tmp<scalarField>& tpsi, const FieldField<Field, scalar>& interfaceBouCoeffs, const lduInterfaceFieldPtrsList& interfaces, const direction cmpt ) const { scalar* __restrict__ ApsiPtr = Apsi.begin(); const scalarField& psi = tpsi(); const scalar* const __restrict__ psiPtr = psi.begin(); const scalar* const __restrict__ diagPtr = diag().begin(); const label* const __restrict__ uPtr = lduAddr().upperAddr().begin(); const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin(); const scalar* const __restrict__ upperPtr = upper().begin(); const scalar* const __restrict__ lowerPtr = lower().begin(); // Initialise the update of interfaced interfaces initMatrixInterfaces ( interfaceBouCoeffs, interfaces, psi, Apsi, cmpt ); const label nCells = diag().size(); for (label cell=0; cell<nCells; cell++) { ApsiPtr[cell] = diagPtr[cell]*psiPtr[cell]; } const label nFaces = upper().size(); for (label face=0; face<nFaces; face++) { ApsiPtr[uPtr[face]] += lowerPtr[face]*psiPtr[lPtr[face]]; ApsiPtr[lPtr[face]] += upperPtr[face]*psiPtr[uPtr[face]]; } // Update interface interfaces updateMatrixInterfaces ( interfaceBouCoeffs, interfaces, psi, Apsi, cmpt ); tpsi.clear(); }
void Foam::LduMatrix<Type, DType, LUType>::Amul ( Field<Type>& Apsi, const tmp<Field<Type>>& tpsi ) const { Type* __restrict__ ApsiPtr = Apsi.begin(); const Field<Type>& psi = tpsi(); const Type* const __restrict__ psiPtr = psi.begin(); const DType* const __restrict__ diagPtr = diag().begin(); const label* const __restrict__ uPtr = lduAddr().upperAddr().begin(); const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin(); const LUType* const __restrict__ upperPtr = upper().begin(); const LUType* const __restrict__ lowerPtr = lower().begin(); // Initialise the update of interfaced interfaces initMatrixInterfaces ( interfacesUpper_, psi, Apsi ); const label nCells = diag().size(); for (label cell=0; cell<nCells; cell++) { ApsiPtr[cell] = dot(diagPtr[cell], psiPtr[cell]); } const label nFaces = upper().size(); for (label face=0; face<nFaces; face++) { ApsiPtr[uPtr[face]] += dot(lowerPtr[face], psiPtr[lPtr[face]]); ApsiPtr[lPtr[face]] += dot(upperPtr[face], psiPtr[uPtr[face]]); } // Update interface interfaces updateMatrixInterfaces ( interfacesUpper_, psi, Apsi ); tpsi.clear(); }
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; }
Foam::lduMatrix::solverPerformance Foam::fvMatrix<Type>::solve ( const dictionary& solverControls ) { if (debug) { Info<< "fvMatrix<Type>::solve(const dictionary&) : " "solving fvMatrix<Type>" << endl; } lduSolverPerformance solverPerfVec ( "fvMatrix<Type>::solve", 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 implicit part by updateMatrixInterfaces within // the component loop. addBoundarySource(source); typename Type::labelType validComponents ( pow ( psi_.mesh().solutionD(), pTraits<typename powProduct<Vector<label>, Type::rank>::type>::zero ) ); // Make a copy of interfaces: no longer a reference // HJ, 20/Nov/2007 lduInterfaceFieldPtrsList interfaces = psi_.boundaryField().interfaces(); 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) ); // 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 ); lduMatrix::solverPerformance solverPerf; // Solver call solverPerf = lduMatrix::solver::New ( psi_.name() + pTraits<Type>::componentNames[cmpt], *this, bouCoeffsCmpt, intCoeffsCmpt, interfaces, solverControls )->solve(psiCmpt, sourceCmpt, cmpt); solverPerf.print(); if ( solverPerf.initialResidual() > solverPerfVec.initialResidual() && !solverPerf.singular() ) { solverPerfVec = solverPerf; } psi_.internalField().replace(cmpt, psiCmpt); diag() = saveDiag; } psi_.correctBoundaryConditions(); return solverPerfVec; }
void Foam::lduMatrix::residual ( scalarField& rA, const scalarField& psi, const scalarField& source, const FieldField<Field, scalar>& interfaceBouCoeffs, const lduInterfaceFieldPtrsList& interfaces, const direction cmpt ) const { scalar* __restrict__ rAPtr = rA.begin(); const scalar* const __restrict__ psiPtr = psi.begin(); const scalar* const __restrict__ diagPtr = diag().begin(); const scalar* const __restrict__ sourcePtr = source.begin(); const label* const __restrict__ uPtr = lduAddr().upperAddr().begin(); const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin(); const scalar* const __restrict__ upperPtr = upper().begin(); const scalar* const __restrict__ lowerPtr = lower().begin(); // Parallel boundary initialisation. // Note: there is a change of sign in the coupled // interface update. The reason for this is that the // internal coefficients are all located at the l.h.s. of // the matrix whereas the "implicit" coefficients on the // coupled boundaries are all created as if the // coefficient contribution is of a source-kind (i.e. they // have a sign as if they are on the r.h.s. of the matrix. // To compensate for this, it is necessary to turn the // sign of the contribution. FieldField<Field, scalar> mBouCoeffs(interfaceBouCoeffs.size()); forAll(mBouCoeffs, patchi) { if (interfaces.set(patchi)) { mBouCoeffs.set(patchi, -interfaceBouCoeffs[patchi]); } } // Initialise the update of interfaced interfaces initMatrixInterfaces ( mBouCoeffs, interfaces, psi, rA, cmpt ); const label nCells = diag().size(); for (label cell=0; cell<nCells; cell++) { rAPtr[cell] = sourcePtr[cell] - diagPtr[cell]*psiPtr[cell]; } const label nFaces = upper().size(); for (label face=0; face<nFaces; face++) { rAPtr[uPtr[face]] -= lowerPtr[face]*psiPtr[lPtr[face]]; rAPtr[lPtr[face]] -= upperPtr[face]*psiPtr[uPtr[face]]; } // Update interface interfaces updateMatrixInterfaces ( mBouCoeffs, interfaces, psi, rA, cmpt ); }