Foam::symGaussSeidelPrecon::symGaussSeidelPrecon ( const lduMatrix& matrix, const FieldField<Field, scalar>& coupleBouCoeffs, const FieldField<Field, scalar>& coupleIntCoeffs, const lduInterfaceFieldPtrsList& interfaces, const dictionary& dict ) : lduPreconditioner ( matrix, coupleBouCoeffs, coupleIntCoeffs, interfaces ), mBouCoeffs_(coupleBouCoeffs.size()), bPrime_(matrix.lduAddr().size()) { forAll(mBouCoeffs_, i) { if (interfaces_.set(i)) { mBouCoeffs_.set(i, -coupleBouCoeffs_[i]); } } }
Foam::coupledSolverPerformance Foam::coupledSmoothSolver::solve ( FieldField<Field, scalar>& x, const FieldField<Field, scalar>& b, const direction cmpt ) const { // Prepare solver performance coupledSolverPerformance solverPerf(typeName, fieldName()); // Do a minimum number of sweeps // HJ, 19/Jan/2009 if (minIter() > 0) { autoPtr<coupledLduSmoother> smootherPtr = coupledLduSmoother::New ( matrix_, bouCoeffs_, intCoeffs_, interfaces_, dict() ); smootherPtr->smooth ( x, b, cmpt, minIter() ); solverPerf.nIterations() += minIter(); } // Now do normal sweeps. HJ, 19/Jan/2009 FieldField<Field, scalar> Ax(x.size()); FieldField<Field, scalar> temp(x.size()); forAll (x, rowI) { Ax.set(rowI, new scalarField(x[rowI].size(), 0)); temp.set(rowI, new scalarField(x[rowI].size(), 0)); }
Foam::coupledSolverPerformance Foam::coupledBicgSolver::solve ( FieldField<Field, scalar>& x, const FieldField<Field, scalar>& b, const direction cmpt ) const { // Prepare solver performance coupledSolverPerformance solverPerf(typeName, fieldName()); FieldField<Field, scalar> wA(x.size()); FieldField<Field, scalar> rA(x.size()); forAll (x, rowI) { wA.set(rowI, new scalarField(x[rowI].size(), 0)); rA.set(rowI, new scalarField(x[rowI].size(), 0)); }
void Foam::GaussSeidelSmoother::smooth ( const word& fieldName_, scalarField& psi, const lduMatrix& matrix_, const scalarField& source, const FieldField<Field, scalar>& interfaceBouCoeffs_, const lduInterfaceFieldPtrsList& interfaces_, const direction cmpt, const label nSweeps ) { register scalar* psiPtr = psi.begin(); register const label nCells = psi.size(); scalarField bPrime(nCells); register scalar* bPrimePtr = bPrime.begin(); register const scalar* const diagPtr = matrix_.diag().begin(); register const scalar* const upperPtr = matrix_.upper().begin(); register const scalar* const lowerPtr = matrix_.lower().begin(); register const label* const uPtr = matrix_.lduAddr().upperAddr().begin(); register const label* const ownStartPtr = matrix_.lduAddr().ownerStartAddr().begin(); // Parallel boundary initialisation. The parallel boundary is treated // as an effective jacobi interface in the boundary. // 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]); } } for (label sweep=0; sweep<nSweeps; sweep++) { bPrime = source; matrix_.initMatrixInterfaces ( mBouCoeffs, interfaces_, psi, bPrime, cmpt ); matrix_.updateMatrixInterfaces ( mBouCoeffs, interfaces_, psi, bPrime, cmpt ); register scalar curPsi; register label fStart; register label fEnd = ownStartPtr[0]; for (register label cellI=0; cellI<nCells; cellI++) { // Start and end of this row fStart = fEnd; fEnd = ownStartPtr[cellI + 1]; // Get the accumulated neighbour side curPsi = bPrimePtr[cellI]; // Accumulate the owner product side for (register label curFace=fStart; curFace<fEnd; curFace++) { curPsi -= upperPtr[curFace]*psiPtr[uPtr[curFace]]; } // Finish current psi curPsi /= diagPtr[cellI]; // Distribute the neighbour side using current psi for (register label curFace=fStart; curFace<fEnd; curFace++) { bPrimePtr[uPtr[curFace]] -= lowerPtr[curFace]*curPsi; } psiPtr[cellI] = curPsi; } } }
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 ); }