1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-6 H. Jasak All rights reserved
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 \*---------------------------------------------------------------------------*/
27 #include "BlockLduMatrix.H"
30 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
33 void Foam::BlockLduMatrix<Type>::sumDiag()
35 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
36 typedef typename TypeCoeffField::linearTypeField linearTypeField;
37 typedef typename TypeCoeffField::squareTypeField squareTypeField;
39 TypeCoeffField& Diag = this->diag();
41 const unallocLabelList& l = lduAddr().lowerAddr();
42 const unallocLabelList& u = lduAddr().upperAddr();
44 if (this->symmetric())
46 // Symmetric matrix: re-use upper transpose for lower coefficients
48 const TypeCoeffField& Upper =
49 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
53 Upper.activeType() == blockCoeffBase::SQUARE
54 || Diag.activeType() == blockCoeffBase::SQUARE
57 const squareTypeField& activeUpper = Upper.asSquare();
58 squareTypeField& activeDiag = Diag.asSquare();
60 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
62 activeDiag[l[coeffI]] += activeUpper[coeffI].T();
63 activeDiag[u[coeffI]] += activeUpper[coeffI];
68 Upper.activeType() == blockCoeffBase::LINEAR
69 || Diag.activeType() == blockCoeffBase::LINEAR
72 const linearTypeField& activeUpper = Upper.asLinear();
73 linearTypeField& activeDiag = Diag.asLinear();
75 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
77 activeDiag[l[coeffI]] += activeUpper[coeffI];
78 activeDiag[u[coeffI]] += activeUpper[coeffI];
83 Upper.activeType() == blockCoeffBase::SCALAR
84 || Diag.activeType() == blockCoeffBase::SCALAR
87 const scalarTypeField& activeUpper = Upper.asScalar();
88 scalarTypeField& activeDiag = Diag.asScalar();
90 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
92 activeDiag[l[coeffI]] += activeUpper[coeffI];
93 activeDiag[u[coeffI]] += activeUpper[coeffI];
97 else if (this->asymmetric())
99 // Full asymmetric matrix
101 const TypeCoeffField& Lower =
102 const_cast<const BlockLduMatrix<Type>&>(*this).lower();
104 const TypeCoeffField& Upper =
105 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
109 Lower.activeType() == blockCoeffBase::SQUARE
110 || Upper.activeType() == blockCoeffBase::SQUARE
111 || Diag.activeType() == blockCoeffBase::SQUARE
114 const squareTypeField& activeLower = Lower.asSquare();
115 const squareTypeField& activeUpper = Upper.asSquare();
116 squareTypeField& activeDiag = Diag.asSquare();
118 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
120 activeDiag[l[coeffI]] += activeLower[coeffI];
121 activeDiag[u[coeffI]] += activeUpper[coeffI];
126 Lower.activeType() == blockCoeffBase::LINEAR
127 || Upper.activeType() == blockCoeffBase::LINEAR
128 || Diag.activeType() == blockCoeffBase::LINEAR
131 const linearTypeField& activeLower = Lower.asLinear();
132 const linearTypeField& activeUpper = Upper.asLinear();
133 linearTypeField& activeDiag = Diag.asLinear();
135 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
137 activeDiag[l[coeffI]] += activeLower[coeffI];
138 activeDiag[u[coeffI]] += activeUpper[coeffI];
143 Lower.activeType() == blockCoeffBase::SCALAR
144 || Upper.activeType() == blockCoeffBase::SCALAR
145 || Diag.activeType() == blockCoeffBase::SCALAR
148 const scalarTypeField& activeLower = Lower.asScalar();
149 const scalarTypeField& activeUpper = Upper.asScalar();
150 scalarTypeField& activeDiag = Diag.asScalar();
152 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
154 activeDiag[l[coeffI]] += activeLower[coeffI];
155 activeDiag[u[coeffI]] += activeUpper[coeffI];
161 FatalErrorIn("void BlockLduMatrix<Type>::sumDiag()")
162 << "No off-diagonal available"
163 << abort(FatalError);
169 void Foam::BlockLduMatrix<Type>::negSumDiag()
171 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
172 typedef typename TypeCoeffField::linearTypeField linearTypeField;
173 typedef typename TypeCoeffField::squareTypeField squareTypeField;
175 TypeCoeffField& Diag = this->diag();
177 const unallocLabelList& l = lduAddr().lowerAddr();
178 const unallocLabelList& u = lduAddr().upperAddr();
180 if (this->symmetric())
182 // Symmetric matrix: re-use upper transpose for lower coefficients
184 const TypeCoeffField& Upper =
185 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
189 Upper.activeType() == blockCoeffBase::SQUARE
190 || Diag.activeType() == blockCoeffBase::SQUARE
193 const squareTypeField& activeUpper = Upper.asSquare();
194 squareTypeField& activeDiag = Diag.asSquare();
196 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
198 activeDiag[l[coeffI]] -= activeUpper[coeffI].T();
199 activeDiag[u[coeffI]] -= activeUpper[coeffI];
204 Upper.activeType() == blockCoeffBase::LINEAR
205 || Diag.activeType() == blockCoeffBase::LINEAR
208 const linearTypeField& activeUpper = Upper.asLinear();
209 linearTypeField& activeDiag = Diag.asLinear();
211 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
213 activeDiag[l[coeffI]] -= activeUpper[coeffI];
214 activeDiag[u[coeffI]] -= activeUpper[coeffI];
219 Upper.activeType() == blockCoeffBase::SCALAR
220 || Diag.activeType() == blockCoeffBase::SCALAR
223 const scalarTypeField& activeUpper = Upper.asScalar();
224 scalarTypeField& activeDiag = Diag.asScalar();
226 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
228 activeDiag[l[coeffI]] -= activeUpper[coeffI];
229 activeDiag[u[coeffI]] -= activeUpper[coeffI];
233 else if (this->asymmetric())
235 // Full asymmetric matrix
237 const TypeCoeffField& Lower =
238 const_cast<const BlockLduMatrix<Type>&>(*this).lower();
240 const TypeCoeffField& Upper =
241 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
245 Lower.activeType() == blockCoeffBase::SQUARE
246 || Upper.activeType() == blockCoeffBase::SQUARE
247 || Diag.activeType() == blockCoeffBase::SQUARE
250 const squareTypeField& activeLower = Lower.asSquare();
251 const squareTypeField& activeUpper = Upper.asSquare();
252 squareTypeField& activeDiag = Diag.asSquare();
254 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
256 activeDiag[l[coeffI]] -= activeLower[coeffI];
257 activeDiag[u[coeffI]] -= activeUpper[coeffI];
262 Lower.activeType() == blockCoeffBase::LINEAR
263 || Upper.activeType() == blockCoeffBase::LINEAR
264 || Diag.activeType() == blockCoeffBase::LINEAR
267 const linearTypeField& activeLower = Lower.asLinear();
268 const linearTypeField& activeUpper = Upper.asLinear();
269 linearTypeField& activeDiag = Diag.asLinear();
271 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
273 activeDiag[l[coeffI]] -= activeLower[coeffI];
274 activeDiag[u[coeffI]] -= activeUpper[coeffI];
279 Lower.activeType() == blockCoeffBase::SCALAR
280 || Upper.activeType() == blockCoeffBase::SCALAR
281 || Diag.activeType() == blockCoeffBase::SCALAR
284 const scalarTypeField& activeLower = Lower.asScalar();
285 const scalarTypeField& activeUpper = Upper.asScalar();
286 scalarTypeField& activeDiag = Diag.asScalar();
288 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
290 activeDiag[l[coeffI]] -= activeLower[coeffI];
291 activeDiag[u[coeffI]] -= activeUpper[coeffI];
297 FatalErrorIn("void BlockLduMatrix<Type>::negSumDiag()")
298 << "No off-diagonal available"
299 << abort(FatalError);
305 void Foam::BlockLduMatrix<Type>::check() const
307 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
308 typedef typename TypeCoeffField::linearTypeField linearTypeField;
309 typedef typename TypeCoeffField::squareTypeField squareTypeField;
312 TypeCoeffField DiagCopy(this->diag().size());
313 // TypeCoeffField DiagCopy = this->diag();
315 const unallocLabelList& l = lduAddr().lowerAddr();
316 const unallocLabelList& u = lduAddr().upperAddr();
318 if (this->symmetric())
320 // Symmetric matrix: re-use upper transpose for lower coefficients
322 const TypeCoeffField& Upper = this->upper();
326 Upper.activeType() == blockCoeffBase::SQUARE
327 || DiagCopy.activeType() == blockCoeffBase::SQUARE
330 const squareTypeField& activeUpper = Upper.asSquare();
331 squareTypeField& activeDiagCopy = DiagCopy.asSquare();
333 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
335 activeDiagCopy[l[coeffI]] += activeUpper[coeffI].T();
336 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
339 Info<< "void BlockLduMatrix<Type>::check() const : "
340 << "Symmetric matrix: raw matrix difference: "
341 << sum(mag(activeDiagCopy))
343 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asSquare()))
348 Upper.activeType() == blockCoeffBase::LINEAR
349 || DiagCopy.activeType() == blockCoeffBase::LINEAR
352 const linearTypeField& activeUpper = Upper.asLinear();
353 linearTypeField& activeDiagCopy = DiagCopy.asLinear();
355 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
357 activeDiagCopy[l[coeffI]] += activeUpper[coeffI];
358 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
361 Info<< "void BlockLduMatrix<Type>::check() const : "
362 << "Symmetric matrix: raw matrix difference: "
363 << sum(mag(activeDiagCopy))
365 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asLinear()))
370 Upper.activeType() == blockCoeffBase::SCALAR
371 || DiagCopy.activeType() == blockCoeffBase::SCALAR
374 const scalarTypeField& activeUpper = Upper.asScalar();
375 scalarTypeField& activeDiagCopy = DiagCopy.asScalar();
377 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
379 activeDiagCopy[l[coeffI]] += activeUpper[coeffI];
380 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
383 Info<< "void BlockLduMatrix<Type>::check() const : "
384 << "Symmetric matrix: raw matrix difference: "
385 << sum(mag(activeDiagCopy))
387 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asScalar()))
391 else if (this->asymmetric())
393 // Full asymmetric matrix
395 const TypeCoeffField& Lower = this->lower();
396 const TypeCoeffField& Upper = this->upper();
400 Lower.activeType() == blockCoeffBase::SQUARE
401 || Upper.activeType() == blockCoeffBase::SQUARE
402 || DiagCopy.activeType() == blockCoeffBase::SQUARE
405 const squareTypeField& activeLower = Lower.asSquare();
406 const squareTypeField& activeUpper = Upper.asSquare();
407 squareTypeField& activeDiagCopy = DiagCopy.asSquare();
409 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
411 activeDiagCopy[l[coeffI]] += activeLower[coeffI];
412 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
415 Info<< "void BlockLduMatrix<Type>::check() const : "
416 << "Asymmetric matrix: raw matrix difference: "
417 << sum(mag(activeDiagCopy))
419 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asSquare()))
424 Lower.activeType() == blockCoeffBase::LINEAR
425 || Upper.activeType() == blockCoeffBase::LINEAR
426 || DiagCopy.activeType() == blockCoeffBase::LINEAR
429 const linearTypeField& activeLower = Lower.asLinear();
430 const linearTypeField& activeUpper = Upper.asLinear();
431 linearTypeField& activeDiagCopy = DiagCopy.asLinear();
433 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
435 activeDiagCopy[l[coeffI]] += activeLower[coeffI];
436 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
439 Info<< "void BlockLduMatrix<Type>::check() const : "
440 << "Asymmetric matrix: raw matrix difference: "
441 << sum(mag(activeDiagCopy))
443 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asLinear()))
448 Lower.activeType() == blockCoeffBase::SCALAR
449 || Upper.activeType() == blockCoeffBase::SCALAR
450 || DiagCopy.activeType() == blockCoeffBase::SCALAR
453 const scalarTypeField& activeLower = Lower.asScalar();
454 const scalarTypeField& activeUpper = Upper.asScalar();
455 scalarTypeField& activeDiagCopy = DiagCopy.asScalar();
457 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
459 activeDiagCopy[l[coeffI]] += activeLower[coeffI];
460 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
463 Info<< "void BlockLduMatrix<Type>::check() const : "
464 << "Asymmetric matrix: raw matrix difference: "
465 << sum(mag(activeDiagCopy))
467 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asScalar()))
473 Info<< "void BlockLduMatrix<Type>::check() const : "
474 << "Diagonal matrix" << endl;
480 void Foam::BlockLduMatrix<Type>::relax
482 const Field<Type>& x,
487 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
488 typedef typename TypeCoeffField::linearTypeField linearTypeField;
489 typedef typename TypeCoeffField::squareTypeField squareTypeField;
491 //HJ Missing code: add coupling coefficients to under-relaxation
499 TypeCoeffField& Diag = this->diag();
501 // Create multiplication function object
502 typename BlockCoeff<Type>::multiply mult;
504 const unallocLabelList& l = lduAddr().lowerAddr();
505 const unallocLabelList& u = lduAddr().upperAddr();
507 if (this->symmetric())
509 // Symmetric matrix: re-use upper transpose for lower coefficients
511 const TypeCoeffField& Upper =
512 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
516 Upper.activeType() == blockCoeffBase::SQUARE
517 || Diag.activeType() == blockCoeffBase::SQUARE
520 const squareTypeField& activeUpper = Upper.asSquare();
521 squareTypeField& activeDiag = Diag.asSquare();
523 // Make a copy of diagonal before relaxation
524 squareTypeField activeDiagOld = activeDiag;
526 // There are options for under-relaxing the block diagonal
527 // coefficient. Currently, the complete diagonal block is
528 // under-relaxed. There's no checking on the off-diag sum
530 squareTypeField sumOff
533 pTraits<typename TypeCoeffField::squareType>::zero
536 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
538 sumOff[u[coeffI]] += cmptMag(activeUpper[coeffI].T());
539 sumOff[l[coeffI]] += cmptMag(activeUpper[coeffI]);
542 activeDiag = max(activeDiag, sumOff);
543 activeDiag *= 1.0/alpha;
545 // Add the relaxation contribution to b
548 b[i] += mult(activeDiag[i] - activeDiagOld[i], x[i]);
553 Upper.activeType() == blockCoeffBase::LINEAR
554 || Diag.activeType() == blockCoeffBase::LINEAR
557 const linearTypeField& activeUpper = Upper.asLinear();
558 linearTypeField& activeDiag = Diag.asLinear();
560 // Make a copy of diagonal before relaxation
561 linearTypeField activeDiagOld = activeDiag;
563 linearTypeField sumOff
566 pTraits<typename TypeCoeffField::linearType>::zero
569 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
571 sumOff[u[coeffI]] += cmptMag(activeUpper[coeffI]);
572 sumOff[l[coeffI]] += cmptMag(activeUpper[coeffI]);
575 activeDiag = max(activeDiag, sumOff);
576 activeDiag *= 1.0/alpha;
578 // Add the relaxation contribution to b
581 b[i] += mult(activeDiag[i] - activeDiagOld[i], x[i]);
586 Upper.activeType() == blockCoeffBase::SCALAR
587 || Diag.activeType() == blockCoeffBase::SCALAR
590 const scalarTypeField& activeUpper = Upper.asScalar();
591 scalarTypeField& activeDiag = Diag.asScalar();
593 // Make a copy of diagonal before relaxation
594 scalarTypeField activeDiagOld = activeDiag;
596 scalarTypeField sumOff
599 pTraits<typename TypeCoeffField::scalarType>::zero
602 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
604 sumOff[u[coeffI]] += mag(activeUpper[coeffI]);
605 sumOff[l[coeffI]] += mag(activeUpper[coeffI]);
608 activeDiag = max(activeDiag, sumOff);
609 activeDiag *= 1.0/alpha;
611 // Add the relaxation contribution to b
614 b[i] += (activeDiag[i] - activeDiagOld[i])*x[i];
618 else if (this->asymmetric())
620 // Full asymmetric matrix
622 const TypeCoeffField& Lower =
623 const_cast<const BlockLduMatrix<Type>&>(*this).lower();
625 const TypeCoeffField& Upper =
626 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
630 Lower.activeType() == blockCoeffBase::SQUARE
631 || Upper.activeType() == blockCoeffBase::SQUARE
632 || Diag.activeType() == blockCoeffBase::SQUARE
635 const squareTypeField& activeLower = Lower.asSquare();
636 const squareTypeField& activeUpper = Upper.asSquare();
637 squareTypeField& activeDiag = Diag.asSquare();
639 // Make a copy of diagonal before relaxation
640 squareTypeField activeDiagOld = activeDiag;
642 // There are options for under-relaxing the block diagonal
643 // coefficient. Currently, the complete diagonal block is
644 // under-relaxed. There's no checking on the off-diag sum
646 squareTypeField sumOff
649 pTraits<typename TypeCoeffField::squareType>::zero
652 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
654 sumOff[u[coeffI]] += cmptMag(activeLower[coeffI]);
655 sumOff[l[coeffI]] += cmptMag(activeUpper[coeffI]);
658 activeDiag = max(activeDiag, sumOff);
659 activeDiag *= 1.0/alpha;
661 // Add the relaxation contribution to b
664 b[i] += mult(activeDiag[i] - activeDiagOld[i], x[i]);
669 Lower.activeType() == blockCoeffBase::LINEAR
670 || Upper.activeType() == blockCoeffBase::LINEAR
671 || Diag.activeType() == blockCoeffBase::LINEAR
674 const linearTypeField& activeLower = Lower.asLinear();
675 const linearTypeField& activeUpper = Upper.asLinear();
676 linearTypeField& activeDiag = Diag.asLinear();
678 // Make a copy of diagonal before relaxation
679 linearTypeField activeDiagOld = activeDiag;
681 linearTypeField sumOff
684 pTraits<typename TypeCoeffField::linearType>::zero
687 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
689 sumOff[u[coeffI]] += cmptMag(activeLower[coeffI]);
690 sumOff[l[coeffI]] += cmptMag(activeUpper[coeffI]);
693 activeDiag = max(activeDiag, sumOff);
694 activeDiag *= 1.0/alpha;
696 // Add the relaxation contribution to b
699 b[i] += mult(activeDiag[i] - activeDiagOld[i], x[i]);
704 Lower.activeType() == blockCoeffBase::SCALAR
705 || Upper.activeType() == blockCoeffBase::SCALAR
706 || Diag.activeType() == blockCoeffBase::SCALAR
709 const scalarTypeField& activeLower = Lower.asScalar();
710 const scalarTypeField& activeUpper = Upper.asScalar();
711 scalarTypeField& activeDiag = Diag.asScalar();
713 // Make a copy of diagonal before relaxation
714 scalarTypeField activeDiagOld = activeDiag;
716 scalarTypeField sumOff
719 pTraits<typename TypeCoeffField::scalarType>::zero
722 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
724 sumOff[u[coeffI]] += mag(activeLower[coeffI]);
725 sumOff[l[coeffI]] += mag(activeUpper[coeffI]);
728 activeDiag = max(activeDiag, sumOff);
729 activeDiag *= 1.0/alpha;
731 // Add the relaxation contribution to b
734 b[i] += activeDiag[i] - activeDiagOld[i]*x[i];
742 void Foam::BlockLduMatrix<Type>::setValue
744 const label eqnIndex,
748 BlockConstraint<Type> cp(eqnIndex, value);
750 if (!fixedEqns_.found(eqnIndex))
752 fixedEqns_.insert(eqnIndex, cp);
758 "void BlockLduMatrix<Type>::setValue(const label eqnIndex, "
760 ) << "Adding constraint on an already constrained point."
761 << " Point: " << eqnIndex << endl;
763 fixedEqns_[eqnIndex].combine(cp);
769 Foam::tmp<Foam::Field<Type> > Foam::BlockLduMatrix<Type>::residual
774 Field<Type> Ax(x.size());
781 typename Foam::tmp<Foam::Field<Type> > Foam::BlockLduMatrix<Type>::residual
783 const Field<Type>& x,
787 return b + residual(x);
792 void Foam::BlockLduMatrix<Type>::negate()
809 // Do coupling coefficients
810 coupleUpper_.negate();
811 coupleLower_.negate();
815 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
819 void Foam::BlockLduMatrix<Type>::operator=(const BlockLduMatrix<Type>& A)
825 "void BlockLduMatrix<Type>::operator="
826 "(const BlockLduMatrix<Type>& A)"
827 ) << "attempted assignment to self"
828 << abort(FatalError);
856 // Copy interface data
857 interfaces_ = A.interfaces_;
858 coupleUpper_ = A.coupleUpper_;
859 coupleLower_ = A.coupleLower_;
862 fixedEqns_ = A.fixedEqns_;
867 void Foam::BlockLduMatrix<Type>::operator+=(const BlockLduMatrix<Type>& A)
877 upper() += A.upper();
879 if (this->asymmetric())
881 lower() += A.upper().transpose();
887 upper() += A.upper();
888 lower() += A.lower();
892 coupleUpper_ += A.coupleUpper_;
893 coupleLower_ += A.coupleLower_;
898 void Foam::BlockLduMatrix<Type>::operator-=(const BlockLduMatrix<Type>& A)
908 upper() -= A.upper();
910 if (this->asymmetric())
912 lower() -= A.upper().transpose();
918 upper() -= A.upper();
919 lower() -= A.lower();
923 coupleUpper_ -= A.coupleUpper_;
924 coupleLower_ -= A.coupleLower_;
929 void Foam::BlockLduMatrix<Type>::operator*=(const scalarField& sf)
931 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
932 typedef typename TypeCoeffField::linearTypeField linearTypeField;
933 typedef typename TypeCoeffField::squareTypeField squareTypeField;
935 //HJ Missing code: add coupling coefficients op*=
945 TypeCoeffField& Upper = *upperPtr_;
947 const unallocLabelList& l = lduAddr().lowerAddr();
949 if (Upper.activeType() == blockCoeffBase::SCALAR)
951 scalarTypeField& activeUpper = Upper.asScalar();
953 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
955 activeUpper[coeffI] *= sf[l[coeffI]];
958 else if (Upper.activeType() == blockCoeffBase::LINEAR)
960 linearTypeField& activeUpper = Upper.asLinear();
962 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
964 activeUpper[coeffI] *= sf[l[coeffI]];
967 else if (Upper.activeType() == blockCoeffBase::SQUARE)
969 squareTypeField& activeUpper = Upper.asSquare();
971 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
973 activeUpper[coeffI] *= sf[l[coeffI]];
980 TypeCoeffField& Lower = *lowerPtr_;
982 const unallocLabelList& u = lduAddr().upperAddr();
984 if (Lower.activeType() == blockCoeffBase::SCALAR)
986 scalarTypeField& activeLower = Lower.asScalar();
988 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
990 activeLower[coeffI] *= sf[u[coeffI]];
993 else if (Lower.activeType() == blockCoeffBase::LINEAR)
995 linearTypeField& activeLower = Lower.asLinear();
997 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
999 activeLower[coeffI] *= sf[u[coeffI]];
1002 else if (Lower.activeType() == blockCoeffBase::SQUARE)
1004 squareTypeField& activeLower = Lower.asSquare();
1006 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
1008 activeLower[coeffI] *= sf[u[coeffI]];
1015 template<class Type>
1016 void Foam::BlockLduMatrix<Type>::operator*=(const scalar s)
1039 // ************************************************************************* //