void Foam::DILUPreconditioner::calcReciprocalD ( scalarField& rD, const lduMatrix& matrix ) { scalar* __restrict__ rDPtr = rD.begin(); const label* const __restrict__ uPtr = matrix.lduAddr().upperAddr().begin(); const label* const __restrict__ lPtr = matrix.lduAddr().lowerAddr().begin(); const scalar* const __restrict__ upperPtr = matrix.upper().begin(); const scalar* const __restrict__ lowerPtr = matrix.lower().begin(); label nFaces = matrix.upper().size(); for (label face=0; face<nFaces; face++) { Pout<< "Adapting diagonal for cell:" << uPtr[face] << " contributions from cell " << lPtr[face] << " from " << rDPtr[uPtr[face]]; rDPtr[uPtr[face]] -= upperPtr[face]*lowerPtr[face]/rDPtr[lPtr[face]]; Pout<< " to " << rDPtr[uPtr[face]] << endl; } // Calculate the reciprocal of the preconditioned diagonal label nCells = rD.size(); for (label cell=0; cell<nCells; cell++) { rDPtr[cell] = 1.0/rDPtr[cell]; } }
// add by NUDT Exercise Group-RXG: begin Foam::iluSmoother::iluSmoother ( const word& fieldName, const lduMatrix& matrix, const FieldField<Field, scalar>& coupleBouCoeffs, const FieldField<Field, scalar>& coupleIntCoeffs, const lduInterfaceFieldPtrsList& interfaces ) : lduSmoother ( fieldName, matrix, coupleBouCoeffs, coupleIntCoeffs, interfaces ), precon_ ( matrix, coupleBouCoeffs, coupleIntCoeffs, interfaces ), xCorr_(matrix.lduAddr().size()), residual_(matrix.lduAddr().size()) {}
void Foam::lduMatrix::operator=(const lduMatrix& A) { if (this == &A) { FatalError << "lduMatrix::operator=(const lduMatrix&) : " << "attempted assignment to self" << abort(FatalError); } if (A.lowerPtr_) { lower() = A.lower(); } else if (lowerPtr_) { delete lowerPtr_; lowerPtr_ = NULL; } if (A.upperPtr_) { upper() = A.upper(); } else if (upperPtr_) { delete upperPtr_; upperPtr_ = NULL; } if (A.diagPtr_) { diag() = A.diag(); } }
void Foam::DILUPreconditioner::calcReciprocalD ( scalarField& rD, const lduMatrix& matrix ) { scalar* __restrict__ rDPtr = rD.begin(); const label* const __restrict__ uPtr = matrix.lduAddr().upperAddr().begin(); const label* const __restrict__ lPtr = matrix.lduAddr().lowerAddr().begin(); const scalar* const __restrict__ upperPtr = matrix.upper().begin(); const scalar* const __restrict__ lowerPtr = matrix.lower().begin(); register label nFaces = matrix.upper().size(); for (register label face=0; face<nFaces; face++) { rDPtr[uPtr[face]] -= upperPtr[face]*lowerPtr[face]/rDPtr[lPtr[face]]; } // Calculate the reciprocal of the preconditioned diagonal register label nCells = rD.size(); for (register label cell=0; cell<nCells; cell++) { rDPtr[cell] = 1.0/rDPtr[cell]; } }
Foam::algebraicPairGAMGAgglomeration::algebraicPairGAMGAgglomeration ( const lduMatrix& matrix, const dictionary& dict ) : pairGAMGAgglomeration(matrix.mesh(), dict) { agglomerate(matrix.mesh(), mag(matrix.upper())); }
void Foam::GAMGSolver::scale ( scalarField& field, scalarField& Acf, const lduMatrix& A, const FieldField<Field, scalar>& interfaceLevelBouCoeffs, const lduInterfaceFieldPtrsList& interfaceLevel, const scalarField& source, const direction cmpt ) const { A.Amul ( Acf, field, interfaceLevelBouCoeffs, interfaceLevel, cmpt ); scalar scalingFactorNum = 0.0; scalar scalingFactorDenom = 0.0; forAll(field, i) { scalingFactorNum += source[i]*field[i]; scalingFactorDenom += Acf[i]*field[i]; }
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]); } } }
void Foam::coupledGaussSeidelPrecon::reverseSweepTranspose ( const lduMatrix& matrix, scalarField& x, scalarField& bPrime ) const { const scalarField& diag = matrix.diag(); const scalarField& lower = matrix.lower(); const scalarField& upper = matrix.upper(); const labelList& upperAddr = matrix.lduAddr().upperAddr(); const labelList& ownStartAddr = matrix.lduAddr().ownerStartAddr(); const label nRows = x.size(); label fStart, fEnd; for (register label rowI = nRows - 1; rowI >= 0; rowI--) { // lRow is equal to rowI scalar& curX = x[rowI]; // Grab the accumulated neighbour side curX = bPrime[rowI]; // Start and end of this row fStart = ownStartAddr[rowI]; fEnd = ownStartAddr[rowI + 1]; // Accumulate the owner product side for (register label curCoeff = fStart; curCoeff < fEnd; curCoeff++) { // Transpose multiplication. HJ, 19/Jan/2009 curX -= lower[curCoeff]*x[upperAddr[curCoeff]]; } // Finish current x curX /= diag[rowI]; // Distribute the neighbour side using current x for (register label curCoeff = fStart; curCoeff < fEnd; curCoeff++) { // Transpose multiplication. HJ, 19/Jan/2009 bPrime[upperAddr[curCoeff]] -= upper[curCoeff]*curX; } } }
Foam::procLduMatrix::procLduMatrix ( const lduMatrix& ldum, const FieldField<Field, scalar>& interfaceCoeffs, const lduInterfaceFieldPtrsList& interfaces ) : upperAddr_(ldum.lduAddr().upperAddr()), lowerAddr_(ldum.lduAddr().lowerAddr()), diag_(ldum.diag()), upper_(ldum.upper()), lower_(ldum.lower()) { label nInterfaces = 0; forAll(interfaces, i) { if (interfaces.set(i)) { nInterfaces++; } } interfaces_.setSize(nInterfaces); nInterfaces = 0; forAll(interfaces, i) { if (interfaces.set(i)) { interfaces_.set ( nInterfaces++, new procLduInterface ( interfaces[i], interfaceCoeffs[i] ) ); } } }
Foam::GAMGSolver::GAMGSolver ( const word& fieldName, const lduMatrix& matrix, const FieldField<gpuField, scalar>& interfaceBouCoeffs, const FieldField<gpuField, scalar>& interfaceIntCoeffs, const lduInterfaceFieldPtrsList& interfaces, const dictionary& solverControls ) : lduMatrix::solver ( fieldName, matrix, interfaceBouCoeffs, interfaceIntCoeffs, interfaces, solverControls ), cacheAgglomeration_(true), nPreSweeps_(0), preSweepsLevelMultiplier_(1), maxPreSweeps_(4), nPostSweeps_(2), postSweepsLevelMultiplier_(1), maxPostSweeps_(4), nFinestSweeps_(2), interpolateCorrection_(false), scaleCorrection_(matrix.symmetric()), agglomeration_(GAMGAgglomeration::New(matrix_, controlDict_)), matrixLevels_(agglomeration_.size()), primitiveInterfaceLevels_(agglomeration_.size()), interfaceLevels_(agglomeration_.size()), interfaceLevelsBouCoeffs_(agglomeration_.size()), interfaceLevelsIntCoeffs_(agglomeration_.size()) { readControls(); forAll(agglomeration_, fineLevelIndex) { // Agglomerate on to coarse level mesh agglomerateMatrix ( fineLevelIndex, agglomeration_.meshLevel(fineLevelIndex + 1), agglomeration_.interfaceLevel(fineLevelIndex + 1) ); }
Foam::amgPrecon::amgPrecon ( const lduMatrix& matrix, const FieldField<Field, scalar>& coupleBouCoeffs, const FieldField<Field, scalar>& coupleIntCoeffs, const lduInterfaceFieldPtrsList& interfaceFields, const dictionary& dict ) : lduPreconditioner ( matrix, coupleBouCoeffs, coupleIntCoeffs, interfaceFields ), cycle_(amgCycle::cycleNames_.read(dict.lookup("cycle"))), nPreSweeps_(readLabel(dict.lookup("nPreSweeps"))), nPostSweeps_(readLabel(dict.lookup("nPostSweeps"))), nMaxLevels_(readLabel(dict.lookup("nMaxLevels"))), scale_(dict.lookup("scale")), amgPtr_ ( new amgCycle ( autoPtr<amgLevel> ( new fineAmgLevel ( matrix, coupleBouCoeffs, coupleIntCoeffs, interfaceFields, dict, dict.lookup("policy"), readLabel(dict.lookup("groupSize")), readLabel(dict.lookup("minCoarseEqns")), dict.lookup("smoother") ) ) ) ), xBuffer_(matrix.lduAddr().size()) { // Make coarse levels amgPtr_->makeCoarseLevels(nMaxLevels_); }
Foam::symGaussSeidelPrecon::symGaussSeidelPrecon ( const lduMatrix& matrix, const FieldField<Field, scalar>& coupleBouCoeffs, const FieldField<Field, scalar>& coupleIntCoeffs, const lduInterfaceFieldPtrsList& interfaces ) : lduPreconditioner ( matrix, coupleBouCoeffs, coupleIntCoeffs, interfaces ), bPrime_(matrix.lduAddr().size()) {}
Foam::DILUPreconditioner::DILUPreconditioner ( const lduMatrix& matrix, const FieldField<Field, scalar>& coupleBouCoeffs, const FieldField<Field, scalar>& coupleIntCoeffs, const lduInterfaceFieldPtrsList& interfaces, const dictionary& ) : lduPreconditioner ( matrix, coupleBouCoeffs, coupleIntCoeffs, interfaces ), rD_(matrix.diag()) { calcReciprocalD(rD_, matrix); }
Foam::algebraicPairGAMGAgglomeration::algebraicPairGAMGAgglomeration ( const lduMatrix& matrix, const dictionary& controlDict ) : pairGAMGAgglomeration(matrix.mesh(), controlDict) { const lduMesh& mesh = matrix.mesh(); if (matrix.hasLower()) { agglomerate(mesh, max(mag(matrix.upper()), mag(matrix.lower()))); } else { agglomerate(mesh, mag(matrix.upper())); } }
void Foam::symGaussSeidelSmoother::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 ) { scalar* __restrict__ psiPtr = psi.begin(); const label nCells = psi.size(); scalarField bPrime(nCells); scalar* __restrict__ bPrimePtr = bPrime.begin(); const scalar* const __restrict__ diagPtr = matrix_.diag().begin(); const scalar* const __restrict__ upperPtr = matrix_.upper().begin(); const scalar* const __restrict__ lowerPtr = matrix_.lower().begin(); const label* const __restrict__ uPtr = matrix_.lduAddr().upperAddr().begin(); const label* const __restrict__ 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 = const_cast<FieldField<Field, scalar>&> ( interfaceBouCoeffs_ ); forAll(mBouCoeffs, patchi) { if (interfaces_.set(patchi)) { mBouCoeffs[patchi].negate(); } } for (label sweep=0; sweep<nSweeps; sweep++) { bPrime = source; matrix_.initMatrixInterfaces ( mBouCoeffs, interfaces_, psi, bPrime, cmpt ); matrix_.updateMatrixInterfaces ( mBouCoeffs, interfaces_, psi, bPrime, cmpt ); scalar psii; label fStart; label fEnd = ownStartPtr[0]; for (label celli=0; celli<nCells; celli++) { // Start and end of this row fStart = fEnd; fEnd = ownStartPtr[celli + 1]; // Get the accumulated neighbour side psii = bPrimePtr[celli]; // Accumulate the owner product side for (label facei=fStart; facei<fEnd; facei++) { psii -= upperPtr[facei]*psiPtr[uPtr[facei]]; } // Finish current psi psii /= diagPtr[celli]; // Distribute the neighbour side using current psi for (label facei=fStart; facei<fEnd; facei++) { bPrimePtr[uPtr[facei]] -= lowerPtr[facei]*psii; } psiPtr[celli] = psii; } fStart = ownStartPtr[nCells]; for (label celli=nCells-1; celli>=0; celli--) { // Start and end of this row fEnd = fStart; fStart = ownStartPtr[celli]; // Get the accumulated neighbour side psii = bPrimePtr[celli]; // Accumulate the owner product side for (label facei=fStart; facei<fEnd; facei++) { psii -= upperPtr[facei]*psiPtr[uPtr[facei]]; } // Finish psi for this cell psii /= diagPtr[celli]; // Distribute the neighbour side using psi for this cell for (label facei=fStart; facei<fEnd; facei++) { bPrimePtr[uPtr[facei]] -= lowerPtr[facei]*psii; } psiPtr[celli] = psii; } } // Restore interfaceBouCoeffs_ forAll(mBouCoeffs, patchi) { if (interfaces_.set(patchi)) { mBouCoeffs[patchi].negate(); } } }
Foam::autoPtr<Foam::lduMatrix::solver> Foam::lduMatrix::solver::New ( const word& fieldName, const lduMatrix& matrix, const FieldField<Field, scalar>& interfaceBouCoeffs, const FieldField<Field, scalar>& interfaceIntCoeffs, const lduInterfaceFieldPtrsList& interfaces, const dictionary& solverControls ) { const word name(solverControls.lookup("solver")); if (matrix.diagonal()) { return autoPtr<lduMatrix::solver> ( new diagonalSolver ( fieldName, matrix, interfaceBouCoeffs, interfaceIntCoeffs, interfaces, solverControls ) ); } else if (matrix.symmetric()) { symMatrixConstructorTable::iterator constructorIter = symMatrixConstructorTablePtr_->find(name); if (constructorIter == symMatrixConstructorTablePtr_->end()) { FatalIOErrorIn ( "lduMatrix::solver::New", solverControls ) << "Unknown symmetric matrix solver " << name << nl << nl << "Valid symmetric matrix solvers are :" << endl << symMatrixConstructorTablePtr_->sortedToc() << exit(FatalIOError); } return autoPtr<lduMatrix::solver> ( constructorIter() ( fieldName, matrix, interfaceBouCoeffs, interfaceIntCoeffs, interfaces, solverControls ) ); } else if (matrix.asymmetric()) { asymMatrixConstructorTable::iterator constructorIter = asymMatrixConstructorTablePtr_->find(name); if (constructorIter == asymMatrixConstructorTablePtr_->end()) { FatalIOErrorIn ( "lduMatrix::solver::New", solverControls ) << "Unknown asymmetric matrix solver " << name << nl << nl << "Valid asymmetric matrix solvers are :" << endl << asymMatrixConstructorTablePtr_->sortedToc() << exit(FatalIOError); } return autoPtr<lduMatrix::solver> ( constructorIter() ( fieldName, matrix, interfaceBouCoeffs, interfaceIntCoeffs, interfaces, solverControls ) ); } else { FatalIOErrorIn ( "lduMatrix::solver::New", solverControls ) << "cannot solve incomplete matrix, " "no diagonal or off-diagonal coefficient" << exit(FatalIOError); return autoPtr<lduMatrix::solver>(NULL); } }
void Foam::GAMGSolver::scale ( scalargpuField& field, scalargpuField& Acf, const lduMatrix& A, const FieldField<gpuField, scalar>& interfaceLevelBouCoeffs, const lduInterfaceFieldPtrsList& interfaceLevel, const scalargpuField& source, const direction cmpt ) const { A.Amul ( Acf, field, interfaceLevelBouCoeffs, interfaceLevel, cmpt ); scalar scalingFactorNum = 0.0; scalar scalingFactorDenom = 0.0; scalingFactorNum = thrust::reduce ( thrust::make_transform_iterator ( thrust::make_zip_iterator(thrust::make_tuple ( source.begin(), field.begin() )), multiplyTupleFunctor() ), thrust::make_transform_iterator ( thrust::make_zip_iterator(thrust::make_tuple ( source.end(), field.end() )), multiplyTupleFunctor() ), 0.0, thrust::plus<scalar>() ); scalingFactorDenom = thrust::reduce ( thrust::make_transform_iterator ( thrust::make_zip_iterator(thrust::make_tuple ( Acf.begin(), field.begin() )), multiplyTupleFunctor() ), thrust::make_transform_iterator ( thrust::make_zip_iterator(thrust::make_tuple ( Acf.end(), field.end() )), multiplyTupleFunctor() ), 0.0, thrust::plus<scalar>() ); /* forAll(field, i) { scalingFactorNum += source[i]*field[i]; scalingFactorDenom += Acf[i]*field[i]; } */ vector2D scalingVector(scalingFactorNum, scalingFactorDenom); A.mesh().reduce(scalingVector, sumOp<vector2D>()); scalar sf = scalingVector.x()/stabilise(scalingVector.y(), VSMALL); if (debug >= 2) { Pout<< sf << " "; } const scalargpuField& D = A.diag(); /* forAll(field, i) { field[i] = sf*field[i] + (source[i] - sf*Acf[i])/D[i]; } */ thrust::transform ( field.begin(), field.end(), thrust::make_zip_iterator(thrust::make_tuple ( source.begin(), Acf.begin(), D.begin() )), field.begin(), GAMGSolverScaleFunctor(sf) ); }
void Foam::lduMatrix::operator+=(const lduMatrix& A) { if (A.diagPtr_) { diag() += A.diag(); } if (symmetric() && A.symmetric()) { upper() += A.upper(); } else if (symmetric() && A.asymmetric()) { if (upperPtr_) { lower(); } else { upper(); } upper() += A.upper(); lower() += A.lower(); } else if (asymmetric() && A.symmetric()) { if (A.upperPtr_) { lower() += A.upper(); upper() += A.upper(); } else { lower() += A.lower(); upper() += A.lower(); } } else if (asymmetric() && A.asymmetric()) { lower() += A.lower(); upper() += A.upper(); } else if (diagonal()) { if (A.upperPtr_) { upper() = A.upper(); } if (A.lowerPtr_) { lower() = A.lower(); } } else if (A.diagonal()) { } else { if (debug > 1) { WarningIn("lduMatrix::operator+=(const lduMatrix& A)") << "Unknown matrix type combination" << endl; } } }
Foam::LUscalarMatrix::LUscalarMatrix ( const lduMatrix& ldum, const FieldField<Field, scalar>& interfaceCoeffs, const lduInterfaceFieldPtrsList& interfaces ) : comm_(ldum.mesh().comm()) { if (Pstream::parRun()) { PtrList<procLduMatrix> lduMatrices(Pstream::nProcs(comm_)); label lduMatrixi = 0; lduMatrices.set ( lduMatrixi++, new procLduMatrix ( ldum, interfaceCoeffs, interfaces ) ); if (Pstream::master(comm_)) { for ( int slave=Pstream::firstSlave(); slave<=Pstream::lastSlave(comm_); slave++ ) { lduMatrices.set ( lduMatrixi++, new procLduMatrix ( IPstream ( Pstream::commsTypes::scheduled, slave, 0, // bufSize Pstream::msgType(), comm_ )() ) ); } } else { OPstream toMaster ( Pstream::commsTypes::scheduled, Pstream::masterNo(), 0, // bufSize Pstream::msgType(), comm_ ); procLduMatrix cldum ( ldum, interfaceCoeffs, interfaces ); toMaster<< cldum; } if (Pstream::master(comm_)) { label nCells = 0; forAll(lduMatrices, i) { nCells += lduMatrices[i].size(); } scalarSquareMatrix m(nCells, 0.0); transfer(m); convert(lduMatrices); } } else {
void Foam::lduMatrix::operator-=(const lduMatrix& A) { if (A.diagPtr_) { diag() -= A.diag(); } if (symmetric() && A.symmetric()) { upper() -= A.upper(); } else if (symmetric() && A.asymmetric()) { if (upperPtr_) { lower(); } else { upper(); } upper() -= A.upper(); lower() -= A.lower(); } else if (asymmetric() && A.symmetric()) { if (A.upperPtr_) { lower() -= A.upper(); upper() -= A.upper(); } else { lower() -= A.lower(); upper() -= A.lower(); } } else if (asymmetric() && A.asymmetric()) { lower() -= A.lower(); upper() -= A.upper(); } else if (diagonal()) { if (A.upperPtr_) { upper() = -A.upper(); } if (A.lowerPtr_) { lower() = -A.lower(); } } else if (A.diagonal()) { } else { FatalErrorIn("lduMatrix::operator-=(const lduMatrix& A)") << "Unknown matrix type combination" << abort(FatalError); } }
Foam::FDICPreconditioner::FDICPreconditioner ( const lduMatrix& matrix, const FieldField<Field, scalar>& coupleBouCoeffs, const FieldField<Field, scalar>& coupleIntCoeffs, const lduInterfaceFieldPtrsList& interfaces, const dictionary& ) : lduPreconditioner ( matrix, coupleBouCoeffs, coupleIntCoeffs, interfaces ), rD_(matrix.diag()), rDuUpper_(matrix.upper().size()), rDlUpper_(matrix.upper().size()) { scalar* __restrict__ rDPtr = rD_.begin(); scalar* __restrict__ rDuUpperPtr = rDuUpper_.begin(); scalar* __restrict__ rDlUpperPtr = rDlUpper_.begin(); const label* const __restrict__ uPtr = matrix_.lduAddr().upperAddr().begin(); const label* const __restrict__ lPtr = matrix_.lduAddr().lowerAddr().begin(); const scalar* const __restrict__ upperPtr = matrix_.upper().begin(); register label nCells = rD_.size(); register label nFaces = matrix_.upper().size(); for (register label face=0; face<nFaces; face++) { #ifdef ICC_IA64_PREFETCH __builtin_prefetch (&uPtr[face+96],0,0); __builtin_prefetch (&lPtr[face+96],0,0); __builtin_prefetch (&upperPtr[face+96],0,1); __builtin_prefetch (&rDPtr[lPtr[face+24]],0,1); __builtin_prefetch (&rDPtr[uPtr[face+24]],1,1); #endif rDPtr[uPtr[face]] -= sqr(upperPtr[face])/rDPtr[lPtr[face]]; } #ifdef ICC_IA64_PREFETCH #pragma ivdep #endif // Generate reciprocal FDIC for (register label cell=0; cell<nCells; cell++) { #ifdef ICC_IA64_PREFETCH __builtin_prefetch (&rDPtr[cell+96],0,1); #endif rDPtr[cell] = 1.0/rDPtr[cell]; } #ifdef ICC_IA64_PREFETCH #pragma ivdep #endif for (register label face=0; face<nFaces; face++) { #ifdef ICC_IA64_PREFETCH __builtin_prefetch (&uPtr[face+96],0,0); __builtin_prefetch (&lPtr[face+96],0,0); __builtin_prefetch (&upperPtr[face+96],0,0); __builtin_prefetch (&rDuUpperPtr[face+96],0,0); __builtin_prefetch (&rDlUpperPtr[face+96],0,0); __builtin_prefetch (&rDPtr[uPtr[face+32]],0,1); __builtin_prefetch (&rDPtr[lPtr[face+32]],0,1); #endif rDuUpperPtr[face] = rDPtr[uPtr[face]]*upperPtr[face]; rDlUpperPtr[face] = rDPtr[lPtr[face]]*upperPtr[face]; } }
void Foam::lduMatrix::operator-=(const lduMatrix& A) { if (A.diagPtr_) { diag() -= A.diag(); } if (symmetric() && A.symmetric()) { upper() -= A.upper(); } else if (symmetric() && A.asymmetric()) { if (upperPtr_) { lower(); } else { upper(); } upper() -= A.upper(); lower() -= A.lower(); } else if (asymmetric() && A.symmetric()) { if (A.upperPtr_) { lower() -= A.upper(); upper() -= A.upper(); } else { lower() -= A.lower(); upper() -= A.lower(); } } else if (asymmetric() && A.asymmetric()) { lower() -= A.lower(); upper() -= A.upper(); } else if (diagonal()) { if (A.upperPtr_) { upper() = -A.upper(); } if (A.lowerPtr_) { lower() = -A.lower(); } } else if (A.diagonal()) { } else { if (debug > 1) { WarningIn("lduMatrix::operator-=(const lduMatrix& A)") << "Unknown matrix type combination" << nl << " this :" << " diagonal:" << diagonal() << " symmetric:" << symmetric() << " asymmetric:" << asymmetric() << nl << " A :" << " diagonal:" << A.diagonal() << " symmetric:" << A.symmetric() << " asymmetric:" << A.asymmetric() << endl; } } }
Foam::autoPtr<Foam::lduMatrix::smoother> Foam::lduMatrix::smoother::New ( const word& fieldName, const lduMatrix& matrix, const FieldField<Field, scalar>& interfaceBouCoeffs, const FieldField<Field, scalar>& interfaceIntCoeffs, const lduInterfaceFieldPtrsList& interfaces, const dictionary& solverControls ) { word name; // Handle primitive or dictionary entry const entry& e = solverControls.lookupEntry("smoother", keyType::LITERAL); if (e.isDict()) { e.dict().readEntry("smoother", name); } else { e.stream() >> name; } // not (yet?) needed: // const dictionary& controls = e.isDict() ? e.dict() : dictionary::null; if (matrix.symmetric()) { auto cstrIter = symMatrixConstructorTablePtr_->cfind(name); if (!cstrIter.found()) { FatalIOErrorInFunction(solverControls) << "Unknown symmetric matrix smoother " << name << nl << nl << "Valid symmetric matrix smoothers are :" << endl << symMatrixConstructorTablePtr_->sortedToc() << exit(FatalIOError); } return autoPtr<lduMatrix::smoother> ( cstrIter() ( fieldName, matrix, interfaceBouCoeffs, interfaceIntCoeffs, interfaces ) ); } else if (matrix.asymmetric()) { auto cstrIter = asymMatrixConstructorTablePtr_->cfind(name); if (!cstrIter.found()) { FatalIOErrorInFunction(solverControls) << "Unknown asymmetric matrix smoother " << name << nl << nl << "Valid asymmetric matrix smoothers are :" << endl << asymMatrixConstructorTablePtr_->sortedToc() << exit(FatalIOError); } return autoPtr<lduMatrix::smoother> ( cstrIter() ( fieldName, matrix, interfaceBouCoeffs, interfaceIntCoeffs, interfaces ) ); } FatalIOErrorInFunction(solverControls) << "cannot solve incomplete matrix, " "no diagonal or off-diagonal coefficient" << exit(FatalIOError); return nullptr; }
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; } } }