void Foam::lduMatrix::operator*=(const scalarField& sf) { if (diagPtr_) { *diagPtr_ *= sf; } if (upperPtr_) { scalarField& upper = *upperPtr_; const labelUList& l = lduAddr().lowerAddr(); for (register label face=0; face<upper.size(); face++) { upper[face] *= sf[l[face]]; } } if (lowerPtr_) { scalarField& lower = *lowerPtr_; const labelUList& u = lduAddr().upperAddr(); for (register label face=0; face<lower.size(); face++) { lower[face] *= sf[u[face]]; } } }
void Foam::lduMatrix::operator*=(const scalarField& sf) { if (diagPtr_) { *diagPtr_ *= sf; } if (upperPtr_) { scalarField& upper = *upperPtr_; const unallocLabelList& l = lduAddr().lowerAddr(); for (register label odcI = 0; odcI < upper.size(); odcI++) { upper[odcI] *= sf[l[odcI]]; } } if (lowerPtr_) { scalarField& lower = *lowerPtr_; const unallocLabelList& u = lduAddr().upperAddr(); for (register label odcI = 0; odcI < lower.size(); odcI++) { lower[odcI] *= sf[u[odcI]]; } } }
Foam::tmp<Foam::scalarField > Foam::lduMatrix::H1() const { tmp<scalarField > tH1 ( new scalarField(lduAddr().size(), 0.0) ); if (lowerPtr_ || upperPtr_) { scalarField& H1_ = tH1(); scalar* H1Ptr = H1_.begin(); const label* uPtr = lduAddr().upperAddr().begin(); const label* lPtr = lduAddr().lowerAddr().begin(); const scalar* lowerPtr = lower().begin(); const scalar* upperPtr = upper().begin(); register const label nFaces = upper().size(); for (register label face=0; face<nFaces; face++) { H1Ptr[uPtr[face]] -= lowerPtr[face]; H1Ptr[lPtr[face]] -= upperPtr[face]; } } return tH1; }
void Foam::lduMatrix::H(Foam::gpuField<Type>& Hpsi,const gpuField<Type>& psi) const { Hpsi = pTraits<Type>::zero; if (lowerPtr_ || upperPtr_) { const scalargpuField& Lower = this->lower(); const scalargpuField& Upper = this->upper(); const labelgpuList& l = lduAddr().lowerAddr(); const labelgpuList& u = lduAddr().upperAddr(); matrixOperation ( Hpsi.begin(), Hpsi, lduAddr(), matrixCoeffsMultiplyFunctor<Type,scalar,negateUnaryOperatorFunctor<Type,Type> > ( psi.data(), Upper.data(), u.data(), negateUnaryOperatorFunctor<Type,Type>() ), matrixCoeffsMultiplyFunctor<Type,scalar,negateUnaryOperatorFunctor<Type,Type> > ( psi.data(), Lower.data(), l.data(), negateUnaryOperatorFunctor<Type,Type>() ) ); } }
Foam::tmp<Foam::scalarField > Foam::lduMatrix::H1() const { tmp<scalarField > tH1 ( new scalarField(lduAddr().size(), 0.0) ); if (lowerPtr_ || upperPtr_) { scalarField& H1_ = tH1.ref(); scalar* __restrict__ H1Ptr = H1_.begin(); const label* __restrict__ uPtr = lduAddr().upperAddr().begin(); const label* __restrict__ lPtr = lduAddr().lowerAddr().begin(); const scalar* __restrict__ lowerPtr = lower().begin(); const scalar* __restrict__ upperPtr = upper().begin(); const label nFaces = upper().size(); for (label face=0; face<nFaces; face++) { H1Ptr[uPtr[face]] -= lowerPtr[face]; H1Ptr[lPtr[face]] -= upperPtr[face]; } }
Foam::tmp<Foam::scalarField > Foam::lduMatrix::H1() const { tmp<scalarField > tH1 ( new scalarField(lduAddr().size(), 0.0) ); if (lowerPtr_ || upperPtr_) { scalarField& H1_ = tH1(); scalar* __restrict__ H1Ptr = H1_.begin(); const label* __restrict__ uPtr = lduAddr().upperAddr().begin(); const label* __restrict__ lPtr = lduAddr().lowerAddr().begin(); const scalar* __restrict__ lowerPtr = lower().begin(); const scalar* __restrict__ upperPtr = upper().begin(); register const label nOdcIs = upper().size(); for (register label odcI = 0; odcI < nOdcIs; odcI++) { H1Ptr[uPtr[odcI]] -= lowerPtr[odcI]; H1Ptr[lPtr[odcI]] -= upperPtr[odcI]; } }
Foam::tmp<Foam::Field<Type> > Foam::lduMatrix::H(const Field<Type>& psi) const { tmp<Field<Type> > tHpsi ( new Field<Type>(lduAddr().size(), pTraits<Type>::zero) ); if (lowerPtr_ || upperPtr_) { Field<Type> & Hpsi = tHpsi(); Type* HpsiPtr = Hpsi.begin(); const Type* psiPtr = psi.begin(); const label* uPtr = lduAddr().upperAddr().begin(); const label* lPtr = lduAddr().lowerAddr().begin(); const scalar* lowerPtr = lower().begin(); const scalar* upperPtr = upper().begin(); register const label nFaces = upper().size(); for (register label face=0; face<nFaces; face++) { HpsiPtr[uPtr[face]] -= lowerPtr[face]*psiPtr[lPtr[face]]; HpsiPtr[lPtr[face]] -= upperPtr[face]*psiPtr[uPtr[face]]; } } return tHpsi; }
Foam::tmp<Foam::Field<Type> > Foam::lduMatrix::faceH(const Field<Type>& psi) const { if (lowerPtr_ || upperPtr_) { const scalarField& Lower = const_cast<const lduMatrix&>(*this).lower(); const scalarField& Upper = const_cast<const lduMatrix&>(*this).upper(); const labelUList& l = lduAddr().lowerAddr(); const labelUList& u = lduAddr().upperAddr(); tmp<Field<Type> > tfaceHpsi(new Field<Type> (Lower.size())); Field<Type> & faceHpsi = tfaceHpsi(); for (register label face=0; face<l.size(); face++) { faceHpsi[face] = Upper[face]*psi[u[face]] - Lower[face]*psi[l[face]]; } return tfaceHpsi; } else { FatalErrorIn("lduMatrix::faceH(const Field<Type>& psi) const") << "Cannot calculate faceH" " the matrix does not have any off-diagonal coefficients." << exit(FatalError); return tmp<Field<Type> >(NULL); } }
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(); }
void Foam::lduMatrix::negSumDiag() { const scalarField& Lower = const_cast<const lduMatrix&>(*this).lower(); const scalarField& Upper = const_cast<const lduMatrix&>(*this).upper(); scalarField& Diag = diag(); const labelUList& l = lduAddr().lowerAddr(); const labelUList& u = lduAddr().upperAddr(); for (register label face=0; face<l.size(); face++) { Diag[l[face]] -= Lower[face]; Diag[u[face]] -= Upper[face]; } }
void Foam::lduMatrix::negSumDiag() { const scalarField& Lower = const_cast<const lduMatrix&>(*this).lower(); const scalarField& Upper = const_cast<const lduMatrix&>(*this).upper(); scalarField& Diag = diag(); const unallocLabelList& l = lduAddr().lowerAddr(); const unallocLabelList& u = lduAddr().upperAddr(); for (register label odcI = 0; odcI < l.size(); odcI++) { Diag[l[odcI]] -= Lower[odcI]; Diag[u[odcI]] -= Upper[odcI]; } }
void Foam::lduMatrix::sumA ( scalarField& sumA, const FieldField<Field, scalar>& interfaceBouCoeffs, const lduInterfaceFieldPtrsList& interfaces ) const { scalar* __restrict__ sumAPtr = sumA.begin(); const scalar* __restrict__ diagPtr = diag().begin(); const label* __restrict__ uPtr = lduAddr().upperAddr().begin(); const label* __restrict__ lPtr = lduAddr().lowerAddr().begin(); const scalar* __restrict__ lowerPtr = lower().begin(); const scalar* __restrict__ upperPtr = upper().begin(); const label nCells = diag().size(); const label nFaces = upper().size(); for (label cell=0; cell<nCells; cell++) { sumAPtr[cell] = diagPtr[cell]; } for (label face=0; face<nFaces; face++) { sumAPtr[uPtr[face]] += lowerPtr[face]; sumAPtr[lPtr[face]] += upperPtr[face]; } // Add the interface internal coefficients to diagonal // and the interface boundary coefficients to the sum-off-diagonal forAll(interfaces, patchi) { if (interfaces.set(patchi)) { const labelUList& pa = lduAddr().patchAddr(patchi); const scalarField& pCoeffs = interfaceBouCoeffs[patchi]; forAll(pa, face) { sumAPtr[pa[face]] -= pCoeffs[face]; } } } }
void Foam::lduMatrix::sumMagOffDiag ( scalarField& sumOff ) const { const scalarField& Lower = const_cast<const lduMatrix&>(*this).lower(); const scalarField& Upper = const_cast<const lduMatrix&>(*this).upper(); const unallocLabelList& l = lduAddr().lowerAddr(); const unallocLabelList& u = lduAddr().upperAddr(); for (register label odcI = 0; odcI < l.size(); odcI++) { sumOff[u[odcI]] += mag(Lower[odcI]); sumOff[l[odcI]] += mag(Upper[odcI]); } }
void Foam::lduMatrix::sumMagOffDiag ( scalarField& sumOff ) const { const scalarField& Lower = const_cast<const lduMatrix&>(*this).lower(); const scalarField& Upper = const_cast<const lduMatrix&>(*this).upper(); const labelUList& l = lduAddr().lowerAddr(); const labelUList& u = lduAddr().upperAddr(); for (register label face = 0; face < l.size(); face++) { sumOff[u[face]] += mag(Lower[face]); sumOff[l[face]] += mag(Upper[face]); } }
Foam::tmp<Foam::gpuField<Type> > Foam::lduMatrix::faceH(const gpuField<Type>& psi) const { if (lowerPtr_ || upperPtr_) { const scalargpuField& Lower = const_cast<const lduMatrix&>(*this).lower(); const scalargpuField& Upper = const_cast<const lduMatrix&>(*this).upper(); const labelgpuList& l = lduAddr().lowerAddr(); const labelgpuList& u = lduAddr().upperAddr(); tmp<gpuField<Type> > tfaceHpsi(new gpuField<Type> (Lower.size())); gpuField<Type> & faceHpsi = tfaceHpsi(); thrust::transform ( thrust::make_zip_iterator(thrust::make_tuple ( Upper.begin(), thrust::make_permutation_iterator(psi.begin(), u.begin()), Lower.begin(), thrust::make_permutation_iterator(psi.begin(), l.begin()) )), thrust::make_zip_iterator(thrust::make_tuple ( Upper.end() , thrust::make_permutation_iterator(psi.begin(), u.end()), Lower.end(), thrust::make_permutation_iterator(psi.begin(), l.end()) )), faceHpsi.begin(), lduMatrixfaceHFunctor<Type>() ); return tfaceHpsi; } else { FatalErrorIn("lduMatrix::faceH(const Field<Type>& psi) const") << "Cannot calculate faceH" " the matrix does not have any off-diagonal coefficients." << exit(FatalError); return tmp<gpuField<Type> >(NULL); } }
Foam::Field<DType>& Foam::LduMatrix<Type, DType, LUType>::diag() { if (!diagPtr_) { diagPtr_ = new Field<DType>(lduAddr().size(), Zero); } return *diagPtr_; }
Foam::Field<Type>& Foam::LduMatrix<Type, DType, LUType>::source() { if (!sourcePtr_) { sourcePtr_ = new Field<Type>(lduAddr().size(), Zero); } return *sourcePtr_; }
Foam::scalarField& Foam::lduMatrix::diag() { if (!diagPtr_) { diagPtr_ = new scalarField(lduAddr().size(), 0.0); } return *diagPtr_; }
void Foam::LduMatrix<Type, DType, LUType>::sumA ( Field<Type>& sumA ) const { Type* __restrict__ sumAPtr = sumA.begin(); const DType* __restrict__ diagPtr = diag().begin(); const label* __restrict__ uPtr = lduAddr().upperAddr().begin(); const label* __restrict__ lPtr = lduAddr().lowerAddr().begin(); const LUType* __restrict__ lowerPtr = lower().begin(); const LUType* __restrict__ upperPtr = upper().begin(); const label nCells = diag().size(); const label nFaces = upper().size(); for (label cell=0; cell<nCells; cell++) { sumAPtr[cell] = dot(diagPtr[cell], pTraits<Type>::one); } for (label face=0; face<nFaces; face++) { sumAPtr[uPtr[face]] += dot(lowerPtr[face], pTraits<Type>::one); sumAPtr[lPtr[face]] += dot(upperPtr[face], pTraits<Type>::one); } // Add the interface internal coefficients to diagonal // and the interface boundary coefficients to the sum-off-diagonal forAll(interfaces_, patchi) { if (interfaces_.set(patchi)) { const unallocLabelList& pa = lduAddr().patchAddr(patchi); const Field<LUType>& pCoeffs = interfacesUpper_[patchi]; forAll(pa, face) { sumAPtr[pa[face]] -= dot(pCoeffs[face], pTraits<Type>::one); } } }
Foam::tmp<Foam::gpuField<Type> > Foam::lduMatrix::H(const gpuField<Type>& psi) const { tmp<gpuField<Type> > tHpsi ( new gpuField<Type>(lduAddr().size(), pTraits<Type>::zero) ); H(tHpsi(),psi); return tHpsi; }
Foam::tmp<Foam::gpuField<Type> > Foam::lduMatrix::H(const gpuField<Type>& psi) const { tmp<gpuField<Type> > tHpsi ( new gpuField<Type>(lduAddr().size(), pTraits<Type>::zero) ); if (lowerPtr_ || upperPtr_) { gpuField<Type> & Hpsi = tHpsi(); const scalargpuField& Lower = this->lower(); const scalargpuField& Upper = this->upper(); const labelgpuList& l = lduAddr().lowerAddr(); const labelgpuList& u = lduAddr().upperAddr(); matrixOperation ( Hpsi.begin(), Hpsi, lduAddr(), matrixCoeffsMultiplyFunctor<Type,scalar,negateUnaryOperatorFunctor<Type,Type> > ( psi.data(), Upper.data(), u.data(), negateUnaryOperatorFunctor<Type,Type>() ), matrixCoeffsMultiplyFunctor<Type,scalar,negateUnaryOperatorFunctor<Type,Type> > ( psi.data(), Lower.data(), l.data(), negateUnaryOperatorFunctor<Type,Type>() ) ); } return tHpsi; }
Foam::scalarField& Foam::lduMatrix::upper() { if (!upperPtr_) { if (lowerPtr_) { upperPtr_ = new scalarField(*lowerPtr_); } else { upperPtr_ = new scalarField(lduAddr().lowerAddr().size(), 0.0); } } return *upperPtr_; }
Foam::Field<LUType>& Foam::LduMatrix<Type, DType, LUType>::lower() { if (!lowerPtr_) { if (upperPtr_) { lowerPtr_ = new Field<LUType>(*upperPtr_); } else { lowerPtr_ = new Field<LUType> ( lduAddr().lowerAddr().size(), Zero ); } } return *lowerPtr_; }
Foam::tmp<Foam::Field<Type> > Foam::BlockLduMatrix<Type>::decoupledH(const Field<Type>& x) const { typedef typename TypeCoeffField::scalarTypeField scalarTypeField; typedef typename TypeCoeffField::linearTypeField linearTypeField; // Create result tmp<Field<Type> > tresult ( new Field<Type>(lduAddr().size(), pTraits<Type>::zero) ); Field<Type>& result = tresult(); const unallocLabelList& u = lduAddr().upperAddr(); const unallocLabelList& l = lduAddr().lowerAddr(); const TypeCoeffField& Upper = this->upper(); // Create multiplication function object typename BlockCoeff<Type>::multiply mult; // Lower multiplication if (symmetric()) { if (Upper.activeType() == blockCoeffBase::SCALAR) { const scalarTypeField& activeUpper = Upper.asScalar(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { result[u[coeffI]] -= mult(activeUpper[coeffI], x[l[coeffI]]); } } else if (Upper.activeType() == blockCoeffBase::LINEAR) { const linearTypeField& activeUpper = Upper.asLinear(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { result[u[coeffI]] -= mult(activeUpper[coeffI], x[l[coeffI]]); } } } else // Asymmetric matrix { const TypeCoeffField& Lower = this->lower(); if (Lower.activeType() == blockCoeffBase::SCALAR) { const scalarTypeField& activeLower = Lower.asScalar(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { result[u[coeffI]] -= mult(activeLower[coeffI], x[l[coeffI]]); } } else if (Lower.activeType() == blockCoeffBase::LINEAR) { const linearTypeField& activeLower = Lower.asLinear(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { result[u[coeffI]] -= mult(activeLower[coeffI], x[l[coeffI]]); } } } // Upper multiplication if (Upper.activeType() == blockCoeffBase::SCALAR) { const scalarTypeField& activeUpper = Upper.asScalar(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { result[l[coeffI]] -= mult(activeUpper[coeffI], x[u[coeffI]]); } } else if (Upper.activeType() == blockCoeffBase::LINEAR) { const linearTypeField& activeUpper = Upper.asLinear(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { result[l[coeffI]] -= mult(activeUpper[coeffI], x[u[coeffI]]); } } return tresult; }
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 ); }
void Foam::BlockLduMatrix<Type>::AmulCore ( TypeField& Ax, const TypeField& x ) const { typedef typename TypeCoeffField::scalarTypeField scalarTypeField; typedef typename TypeCoeffField::linearTypeField linearTypeField; typedef typename TypeCoeffField::squareTypeField squareTypeField; const unallocLabelList& u = lduAddr().upperAddr(); const unallocLabelList& l = lduAddr().lowerAddr(); const TypeCoeffField& Diag = this->diag(); const TypeCoeffField& Upper = this->upper(); // Create multiplication function object typename BlockCoeff<Type>::multiply mult; // Diagonal multiplication, no indirection multiply(Ax, Diag, x); // Lower multiplication if (symmetric()) { if (Upper.activeType() == blockCoeffBase::SCALAR) { const scalarTypeField& activeUpper = Upper.asScalar(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { Ax[u[coeffI]] += mult(activeUpper[coeffI], x[l[coeffI]]); } } else if (Upper.activeType() == blockCoeffBase::LINEAR) { const linearTypeField& activeUpper = Upper.asLinear(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { Ax[u[coeffI]] += mult(activeUpper[coeffI], x[l[coeffI]]); } } else if (Upper.activeType() == blockCoeffBase::SQUARE) { const squareTypeField& activeUpper = Upper.asSquare(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { // Use transpose upper coefficient Ax[u[coeffI]] += mult(activeUpper[coeffI].T(), x[l[coeffI]]); } } } else // Asymmetric matrix { const TypeCoeffField& Lower = this->lower(); if (Lower.activeType() == blockCoeffBase::SCALAR) { const scalarTypeField& activeLower = Lower.asScalar(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { Ax[u[coeffI]] += mult(activeLower[coeffI], x[l[coeffI]]); } } else if (Lower.activeType() == blockCoeffBase::LINEAR) { const linearTypeField& activeLower = Lower.asLinear(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { Ax[u[coeffI]] += mult(activeLower[coeffI], x[l[coeffI]]); } } else if (Lower.activeType() == blockCoeffBase::SQUARE) { const squareTypeField& activeLower = Lower.asSquare(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { Ax[u[coeffI]] += mult(activeLower[coeffI], x[l[coeffI]]); } } } // Upper multiplication if (Upper.activeType() == blockCoeffBase::SCALAR) { const scalarTypeField& activeUpper = Upper.asScalar(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { Ax[l[coeffI]] += mult(activeUpper[coeffI], x[u[coeffI]]); } } else if (Upper.activeType() == blockCoeffBase::LINEAR) { const linearTypeField& activeUpper = Upper.asLinear(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { Ax[l[coeffI]] += mult(activeUpper[coeffI], x[u[coeffI]]); } } else if (Upper.activeType() == blockCoeffBase::SQUARE) { const squareTypeField& activeUpper = Upper.asSquare(); for (register label coeffI = 0; coeffI < u.size(); coeffI++) { Ax[l[coeffI]] += mult(activeUpper[coeffI], x[u[coeffI]]); } } }
void Foam::BlockLduMatrix<Type>::segregateB ( TypeField& sMul, const TypeField& x ) const { typedef typename TypeCoeffField::linearType linearType; typedef typename TypeCoeffField::squareType squareType; typedef typename TypeCoeffField::linearTypeField linearTypeField; typedef typename TypeCoeffField::squareTypeField squareTypeField; const unallocLabelList& u = lduAddr().upperAddr(); const unallocLabelList& l = lduAddr().lowerAddr(); // Diagonal multiplication if (thereIsDiag()) { if (diag().activeType() == blockCoeffBase::SQUARE) { const squareTypeField& activeDiag = this->diag().asSquare(); linearTypeField lf(activeDiag.size()); squareTypeField sf(activeDiag.size()); // Expand and contract contractLinear(lf, activeDiag); expandLinear(sf, lf); sMul -= (activeDiag - sf) & x; } } // Lower multiplication if (thereIsLower()) { if (lower().activeType() == blockCoeffBase::SQUARE) { const squareTypeField& activeLower = this->lower().asSquare(); // Auxiliary variables used in expand/contract linearType lt; squareType st; for (register label coeffI = 0; coeffI < u.size(); coeffI++) { contractLinear(lt, activeLower[coeffI]); expandLinear(st, lt); sMul[u[coeffI]] -= (activeLower[coeffI] - st) & x[l[coeffI]]; } } } // Upper multiplication if (thereIsUpper()) { if (upper().activeType() == blockCoeffBase::SQUARE) { const squareTypeField& activeUpper = this->upper().asSquare(); // Auxiliary variables used in expand/contract linearType lt; squareType st; for (register label coeffI = 0; coeffI < u.size(); coeffI++) { contractLinear(lt, activeUpper[coeffI]); expandLinear(st, lt); sMul[l[coeffI]] -= (activeUpper[coeffI] - st) & x[u[coeffI]]; } // If the matrix is symmetric, the lower triangular product // is also needed if (symmetric()) { for (register label coeffI = 0; coeffI < u.size(); coeffI++) { // Use transpose upper coefficient contractLinear(lt, activeUpper[coeffI]); expandLinear(st, lt); sMul[u[coeffI]] -= (activeUpper[coeffI].T() - st) & x[l[coeffI]]; } } } } }
// deal with the ordering of the faces, the algorithm is split // into two parts. For original faces, the internal faces are // distributed to their owner cells. Once all internal faces are // distributed, the boundary faces are visited and if they are in // the mirror plane they are added to the master cells (the future // boundary faces are not touched). After the first phase, the // internal faces are collected in the cell order and numbering // information is added. Then, the internal faces are mirrored // and the face numbering data is stored for the mirrored section. // Once all the internal faces are mirrored, the boundary faces // are added by mirroring the faces patch by patch. // Distribute internal faces labelListList newCellFaces(oldCells.size()); const unallocLabelList& oldOwnerStart = lduAddr().ownerStartAddr(); forAll (newCellFaces, cellI) { labelList& curFaces = newCellFaces[cellI]; const label s = oldOwnerStart[cellI]; const label e = oldOwnerStart[cellI + 1]; curFaces.setSize(e - s); forAll (curFaces, i) { curFaces[i] = s + i; } }
// deal with the ordering of the faces, the algorithm is split // into two parts. For original faces, the internal faces are // distributed to their owner cells. Once all internal faces are // distributed, the boundary faces are visited and if they are in // the mirror plane they are added to the master cells (the future // boundary faces are not touched). After the first phase, the // internal faces are collected in the cell order and numbering // information is added. Then, the internal faces are mirrored // and the face numbering data is stored for the mirrored section. // Once all the internal faces are mirrored, the boundary faces // are added by mirroring the faces patch by patch. // Distribute internal faces labelListList newCellFaces(oldCells.size()); const labelUList& oldOwnerStart = lduAddr().ownerStartAddr(); forAll(newCellFaces, cellI) { labelList& curFaces = newCellFaces[cellI]; const label s = oldOwnerStart[cellI]; const label e = oldOwnerStart[cellI + 1]; curFaces.setSize(e - s); forAll(curFaces, i) { curFaces[i] = s + i; } }