1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "BlockLduMatrix.H"
29 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
32 void Foam::BlockLduMatrix<Type>::sumDiag()
34 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
35 typedef typename TypeCoeffField::linearTypeField linearTypeField;
36 typedef typename TypeCoeffField::squareTypeField squareTypeField;
38 TypeCoeffField& Diag = this->diag();
40 const unallocLabelList& l = lduAddr().lowerAddr();
41 const unallocLabelList& u = lduAddr().upperAddr();
43 if (this->symmetric())
45 // Symmetric matrix: re-use upper transpose for lower coefficients
47 const TypeCoeffField& Upper =
48 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
52 Upper.activeType() == blockCoeffBase::SQUARE
53 || Diag.activeType() == blockCoeffBase::SQUARE
56 const squareTypeField& activeUpper = Upper.asSquare();
57 squareTypeField& activeDiag = Diag.asSquare();
59 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
61 activeDiag[l[coeffI]] += activeUpper[coeffI].T();
62 activeDiag[u[coeffI]] += activeUpper[coeffI];
67 Upper.activeType() == blockCoeffBase::LINEAR
68 || Diag.activeType() == blockCoeffBase::LINEAR
71 const linearTypeField& activeUpper = Upper.asLinear();
72 linearTypeField& activeDiag = Diag.asLinear();
74 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
76 activeDiag[l[coeffI]] += activeUpper[coeffI];
77 activeDiag[u[coeffI]] += activeUpper[coeffI];
82 Upper.activeType() == blockCoeffBase::SCALAR
83 || Diag.activeType() == blockCoeffBase::SCALAR
86 const scalarTypeField& activeUpper = Upper.asScalar();
87 scalarTypeField& activeDiag = Diag.asScalar();
89 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
91 activeDiag[l[coeffI]] += activeUpper[coeffI];
92 activeDiag[u[coeffI]] += activeUpper[coeffI];
96 else if (this->asymmetric())
98 // Full asymmetric matrix
100 const TypeCoeffField& Lower =
101 const_cast<const BlockLduMatrix<Type>&>(*this).lower();
103 const TypeCoeffField& Upper =
104 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
108 Lower.activeType() == blockCoeffBase::SQUARE
109 || Upper.activeType() == blockCoeffBase::SQUARE
110 || Diag.activeType() == blockCoeffBase::SQUARE
113 const squareTypeField& activeLower = Lower.asSquare();
114 const squareTypeField& activeUpper = Upper.asSquare();
115 squareTypeField& activeDiag = Diag.asSquare();
117 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
119 activeDiag[l[coeffI]] += activeLower[coeffI];
120 activeDiag[u[coeffI]] += activeUpper[coeffI];
125 Lower.activeType() == blockCoeffBase::LINEAR
126 || Upper.activeType() == blockCoeffBase::LINEAR
127 || Diag.activeType() == blockCoeffBase::LINEAR
130 const linearTypeField& activeLower = Lower.asLinear();
131 const linearTypeField& activeUpper = Upper.asLinear();
132 linearTypeField& activeDiag = Diag.asLinear();
134 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
136 activeDiag[l[coeffI]] += activeLower[coeffI];
137 activeDiag[u[coeffI]] += activeUpper[coeffI];
142 Lower.activeType() == blockCoeffBase::SCALAR
143 || Upper.activeType() == blockCoeffBase::SCALAR
144 || Diag.activeType() == blockCoeffBase::SCALAR
147 const scalarTypeField& activeLower = Lower.asScalar();
148 const scalarTypeField& activeUpper = Upper.asScalar();
149 scalarTypeField& activeDiag = Diag.asScalar();
151 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
153 activeDiag[l[coeffI]] += activeLower[coeffI];
154 activeDiag[u[coeffI]] += activeUpper[coeffI];
160 FatalErrorIn("void BlockLduMatrix<Type>::sumDiag()")
161 << "No off-diagonal available"
162 << abort(FatalError);
168 void Foam::BlockLduMatrix<Type>::negSumDiag()
170 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
171 typedef typename TypeCoeffField::linearTypeField linearTypeField;
172 typedef typename TypeCoeffField::squareTypeField squareTypeField;
174 TypeCoeffField& Diag = this->diag();
176 const unallocLabelList& l = lduAddr().lowerAddr();
177 const unallocLabelList& u = lduAddr().upperAddr();
179 if (this->symmetric())
181 // Symmetric matrix: re-use upper transpose for lower coefficients
183 const TypeCoeffField& Upper =
184 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
188 Upper.activeType() == blockCoeffBase::SQUARE
189 || Diag.activeType() == blockCoeffBase::SQUARE
192 const squareTypeField& activeUpper = Upper.asSquare();
193 squareTypeField& activeDiag = Diag.asSquare();
195 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
197 activeDiag[l[coeffI]] -= activeUpper[coeffI].T();
198 activeDiag[u[coeffI]] -= activeUpper[coeffI];
203 Upper.activeType() == blockCoeffBase::LINEAR
204 || Diag.activeType() == blockCoeffBase::LINEAR
207 const linearTypeField& activeUpper = Upper.asLinear();
208 linearTypeField& activeDiag = Diag.asLinear();
210 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
212 activeDiag[l[coeffI]] -= activeUpper[coeffI];
213 activeDiag[u[coeffI]] -= activeUpper[coeffI];
218 Upper.activeType() == blockCoeffBase::SCALAR
219 || Diag.activeType() == blockCoeffBase::SCALAR
222 const scalarTypeField& activeUpper = Upper.asScalar();
223 scalarTypeField& activeDiag = Diag.asScalar();
225 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
227 activeDiag[l[coeffI]] -= activeUpper[coeffI];
228 activeDiag[u[coeffI]] -= activeUpper[coeffI];
232 else if (this->asymmetric())
234 // Full asymmetric matrix
236 const TypeCoeffField& Lower =
237 const_cast<const BlockLduMatrix<Type>&>(*this).lower();
239 const TypeCoeffField& Upper =
240 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
244 Lower.activeType() == blockCoeffBase::SQUARE
245 || Upper.activeType() == blockCoeffBase::SQUARE
246 || Diag.activeType() == blockCoeffBase::SQUARE
249 const squareTypeField& activeLower = Lower.asSquare();
250 const squareTypeField& activeUpper = Upper.asSquare();
251 squareTypeField& activeDiag = Diag.asSquare();
253 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
255 activeDiag[l[coeffI]] -= activeLower[coeffI];
256 activeDiag[u[coeffI]] -= activeUpper[coeffI];
261 Lower.activeType() == blockCoeffBase::LINEAR
262 || Upper.activeType() == blockCoeffBase::LINEAR
263 || Diag.activeType() == blockCoeffBase::LINEAR
266 const linearTypeField& activeLower = Lower.asLinear();
267 const linearTypeField& activeUpper = Upper.asLinear();
268 linearTypeField& activeDiag = Diag.asLinear();
270 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
272 activeDiag[l[coeffI]] -= activeLower[coeffI];
273 activeDiag[u[coeffI]] -= activeUpper[coeffI];
278 Lower.activeType() == blockCoeffBase::SCALAR
279 || Upper.activeType() == blockCoeffBase::SCALAR
280 || Diag.activeType() == blockCoeffBase::SCALAR
283 const scalarTypeField& activeLower = Lower.asScalar();
284 const scalarTypeField& activeUpper = Upper.asScalar();
285 scalarTypeField& activeDiag = Diag.asScalar();
287 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
289 activeDiag[l[coeffI]] -= activeLower[coeffI];
290 activeDiag[u[coeffI]] -= activeUpper[coeffI];
296 FatalErrorIn("void BlockLduMatrix<Type>::negSumDiag()")
297 << "No off-diagonal available"
298 << abort(FatalError);
304 void Foam::BlockLduMatrix<Type>::check() const
306 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
307 typedef typename TypeCoeffField::linearTypeField linearTypeField;
308 typedef typename TypeCoeffField::squareTypeField squareTypeField;
311 TypeCoeffField DiagCopy(this->diag().size());
312 // TypeCoeffField DiagCopy = this->diag();
314 const unallocLabelList& l = lduAddr().lowerAddr();
315 const unallocLabelList& u = lduAddr().upperAddr();
317 if (this->symmetric())
319 // Symmetric matrix: re-use upper transpose for lower coefficients
321 const TypeCoeffField& Upper = this->upper();
325 Upper.activeType() == blockCoeffBase::SQUARE
326 || DiagCopy.activeType() == blockCoeffBase::SQUARE
329 const squareTypeField& activeUpper = Upper.asSquare();
330 squareTypeField& activeDiagCopy = DiagCopy.asSquare();
332 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
334 activeDiagCopy[l[coeffI]] += activeUpper[coeffI].T();
335 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
338 Info<< "void BlockLduMatrix<Type>::check() const : "
339 << "Symmetric matrix: raw matrix difference: "
340 << sum(mag(activeDiagCopy))
342 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asSquare()))
347 Upper.activeType() == blockCoeffBase::LINEAR
348 || DiagCopy.activeType() == blockCoeffBase::LINEAR
351 const linearTypeField& activeUpper = Upper.asLinear();
352 linearTypeField& activeDiagCopy = DiagCopy.asLinear();
354 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
356 activeDiagCopy[l[coeffI]] += activeUpper[coeffI];
357 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
360 Info<< "void BlockLduMatrix<Type>::check() const : "
361 << "Symmetric matrix: raw matrix difference: "
362 << sum(mag(activeDiagCopy))
364 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asLinear()))
369 Upper.activeType() == blockCoeffBase::SCALAR
370 || DiagCopy.activeType() == blockCoeffBase::SCALAR
373 const scalarTypeField& activeUpper = Upper.asScalar();
374 scalarTypeField& activeDiagCopy = DiagCopy.asScalar();
376 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
378 activeDiagCopy[l[coeffI]] += activeUpper[coeffI];
379 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
382 Info<< "void BlockLduMatrix<Type>::check() const : "
383 << "Symmetric matrix: raw matrix difference: "
384 << sum(mag(activeDiagCopy))
386 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asScalar()))
390 else if (this->asymmetric())
392 // Full asymmetric matrix
394 const TypeCoeffField& Lower = this->lower();
395 const TypeCoeffField& Upper = this->upper();
399 Lower.activeType() == blockCoeffBase::SQUARE
400 || Upper.activeType() == blockCoeffBase::SQUARE
401 || DiagCopy.activeType() == blockCoeffBase::SQUARE
404 const squareTypeField& activeLower = Lower.asSquare();
405 const squareTypeField& activeUpper = Upper.asSquare();
406 squareTypeField& activeDiagCopy = DiagCopy.asSquare();
408 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
410 activeDiagCopy[l[coeffI]] += activeLower[coeffI];
411 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
414 Info<< "void BlockLduMatrix<Type>::check() const : "
415 << "Asymmetric matrix: raw matrix difference: "
416 << sum(mag(activeDiagCopy))
418 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asSquare()))
423 Lower.activeType() == blockCoeffBase::LINEAR
424 || Upper.activeType() == blockCoeffBase::LINEAR
425 || DiagCopy.activeType() == blockCoeffBase::LINEAR
428 const linearTypeField& activeLower = Lower.asLinear();
429 const linearTypeField& activeUpper = Upper.asLinear();
430 linearTypeField& activeDiagCopy = DiagCopy.asLinear();
432 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
434 activeDiagCopy[l[coeffI]] += activeLower[coeffI];
435 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
438 Info<< "void BlockLduMatrix<Type>::check() const : "
439 << "Asymmetric matrix: raw matrix difference: "
440 << sum(mag(activeDiagCopy))
442 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asLinear()))
447 Lower.activeType() == blockCoeffBase::SCALAR
448 || Upper.activeType() == blockCoeffBase::SCALAR
449 || DiagCopy.activeType() == blockCoeffBase::SCALAR
452 const scalarTypeField& activeLower = Lower.asScalar();
453 const scalarTypeField& activeUpper = Upper.asScalar();
454 scalarTypeField& activeDiagCopy = DiagCopy.asScalar();
456 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
458 activeDiagCopy[l[coeffI]] += activeLower[coeffI];
459 activeDiagCopy[u[coeffI]] += activeUpper[coeffI];
462 Info<< "void BlockLduMatrix<Type>::check() const : "
463 << "Asymmetric matrix: raw matrix difference: "
464 << sum(mag(activeDiagCopy))
466 << sum(mag(activeDiagCopy))/sum(mag(this->diag().asScalar()))
472 Info<< "void BlockLduMatrix<Type>::check() const : "
473 << "Diagonal matrix" << endl;
479 void Foam::BlockLduMatrix<Type>::relax
481 const Field<Type>& x,
486 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
487 typedef typename TypeCoeffField::linearTypeField linearTypeField;
488 typedef typename TypeCoeffField::squareTypeField squareTypeField;
490 //HJ Missing code: add coupling coefficients to under-relaxation
498 TypeCoeffField& Diag = this->diag();
500 // Create multiplication function object
501 typename BlockCoeff<Type>::multiply mult;
503 const unallocLabelList& l = lduAddr().lowerAddr();
504 const unallocLabelList& u = lduAddr().upperAddr();
506 if (this->symmetric())
508 // Symmetric matrix: re-use upper transpose for lower coefficients
510 const TypeCoeffField& Upper =
511 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
515 Upper.activeType() == blockCoeffBase::SQUARE
516 || Diag.activeType() == blockCoeffBase::SQUARE
519 const squareTypeField& activeUpper = Upper.asSquare();
520 squareTypeField& activeDiag = Diag.asSquare();
522 // Make a copy of diagonal before relaxation
523 squareTypeField activeDiagOld = activeDiag;
525 // There are options for under-relaxing the block diagonal
526 // coefficient. Currently, the complete diagonal block is
527 // under-relaxed. There's no checking on the off-diag sum
529 squareTypeField sumOff
532 pTraits<typename TypeCoeffField::squareType>::zero
535 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
537 sumOff[u[coeffI]] += cmptMag(activeUpper[coeffI].T());
538 sumOff[l[coeffI]] += cmptMag(activeUpper[coeffI]);
541 // Reconsider under-relaxation of square blocks.
542 // HJ, 23/Sep/2011 (2 places)
543 activeDiag = max(activeDiag, sumOff);
544 activeDiag *= 1.0/alpha;
546 // Add the relaxation contribution to b
549 b[i] += mult(activeDiag[i] - activeDiagOld[i], x[i]);
554 Upper.activeType() == blockCoeffBase::LINEAR
555 || Diag.activeType() == blockCoeffBase::LINEAR
558 const linearTypeField& activeUpper = Upper.asLinear();
559 linearTypeField& activeDiag = Diag.asLinear();
561 // Make a copy of diagonal before relaxation
562 linearTypeField activeDiagOld = activeDiag;
564 linearTypeField sumOff
567 pTraits<typename TypeCoeffField::linearType>::zero
570 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
572 sumOff[u[coeffI]] += cmptMag(activeUpper[coeffI]);
573 sumOff[l[coeffI]] += cmptMag(activeUpper[coeffI]);
576 activeDiag = max(activeDiag, sumOff);
577 activeDiag *= 1.0/alpha;
579 // Add the relaxation contribution to b
582 b[i] += mult(activeDiag[i] - activeDiagOld[i], x[i]);
587 Upper.activeType() == blockCoeffBase::SCALAR
588 || Diag.activeType() == blockCoeffBase::SCALAR
591 const scalarTypeField& activeUpper = Upper.asScalar();
592 scalarTypeField& activeDiag = Diag.asScalar();
594 // Make a copy of diagonal before relaxation
595 scalarTypeField activeDiagOld = activeDiag;
597 scalarTypeField sumOff
600 pTraits<typename TypeCoeffField::scalarType>::zero
603 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
605 sumOff[u[coeffI]] += mag(activeUpper[coeffI]);
606 sumOff[l[coeffI]] += mag(activeUpper[coeffI]);
609 activeDiag = max(activeDiag, sumOff);
610 activeDiag *= 1.0/alpha;
612 // Add the relaxation contribution to b
615 b[i] += (activeDiag[i] - activeDiagOld[i])*x[i];
619 else if (this->asymmetric())
621 // Full asymmetric matrix
623 const TypeCoeffField& Lower =
624 const_cast<const BlockLduMatrix<Type>&>(*this).lower();
626 const TypeCoeffField& Upper =
627 const_cast<const BlockLduMatrix<Type>&>(*this).upper();
631 Lower.activeType() == blockCoeffBase::SQUARE
632 || Upper.activeType() == blockCoeffBase::SQUARE
633 || Diag.activeType() == blockCoeffBase::SQUARE
636 const squareTypeField& activeLower = Lower.asSquare();
637 const squareTypeField& activeUpper = Upper.asSquare();
638 squareTypeField& activeDiag = Diag.asSquare();
640 // Make a copy of diagonal before relaxation
641 squareTypeField activeDiagOld = activeDiag;
643 // There are options for under-relaxing the block diagonal
644 // coefficient. Currently, the complete diagonal block is
645 // under-relaxed. There's no checking on the off-diag sum
647 squareTypeField sumOff
650 pTraits<typename TypeCoeffField::squareType>::zero
653 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
655 sumOff[u[coeffI]] += cmptMag(activeLower[coeffI]);
656 sumOff[l[coeffI]] += cmptMag(activeUpper[coeffI]);
659 // Reconsider under-relaxation of square blocks.
660 // HJ, 23/Sep/2011 (2 places)
661 activeDiag = max(activeDiag, sumOff);
662 activeDiag *= 1.0/alpha;
664 // Add the relaxation contribution to b
667 b[i] += mult(activeDiag[i] - activeDiagOld[i], x[i]);
672 Lower.activeType() == blockCoeffBase::LINEAR
673 || Upper.activeType() == blockCoeffBase::LINEAR
674 || Diag.activeType() == blockCoeffBase::LINEAR
677 const linearTypeField& activeLower = Lower.asLinear();
678 const linearTypeField& activeUpper = Upper.asLinear();
679 linearTypeField& activeDiag = Diag.asLinear();
681 // Make a copy of diagonal before relaxation
682 linearTypeField activeDiagOld = activeDiag;
684 linearTypeField sumOff
687 pTraits<typename TypeCoeffField::linearType>::zero
690 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
692 sumOff[u[coeffI]] += cmptMag(activeLower[coeffI]);
693 sumOff[l[coeffI]] += cmptMag(activeUpper[coeffI]);
696 activeDiag = max(activeDiag, sumOff);
697 activeDiag *= 1.0/alpha;
699 // Add the relaxation contribution to b
702 b[i] += mult(activeDiag[i] - activeDiagOld[i], x[i]);
707 Lower.activeType() == blockCoeffBase::SCALAR
708 || Upper.activeType() == blockCoeffBase::SCALAR
709 || Diag.activeType() == blockCoeffBase::SCALAR
712 const scalarTypeField& activeLower = Lower.asScalar();
713 const scalarTypeField& activeUpper = Upper.asScalar();
714 scalarTypeField& activeDiag = Diag.asScalar();
716 // Make a copy of diagonal before relaxation
717 scalarTypeField activeDiagOld = activeDiag;
719 scalarTypeField sumOff
722 pTraits<typename TypeCoeffField::scalarType>::zero
725 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
727 sumOff[u[coeffI]] += mag(activeLower[coeffI]);
728 sumOff[l[coeffI]] += mag(activeUpper[coeffI]);
731 activeDiag = max(activeDiag, sumOff);
732 activeDiag *= 1.0/alpha;
734 // Add the relaxation contribution to b
737 b[i] += activeDiag[i] - activeDiagOld[i]*x[i];
745 void Foam::BlockLduMatrix<Type>::setValue
747 const label eqnIndex,
751 BlockConstraint<Type> cp(eqnIndex, value);
753 if (!fixedEqns_.found(eqnIndex))
755 fixedEqns_.insert(eqnIndex, cp);
761 "void BlockLduMatrix<Type>::setValue(const label eqnIndex, "
763 ) << "Adding constraint on an already constrained point."
764 << " Point: " << eqnIndex << endl;
766 fixedEqns_[eqnIndex].combine(cp);
772 Foam::tmp<Foam::Field<Type> > Foam::BlockLduMatrix<Type>::residual
777 Field<Type> Ax(x.size());
784 typename Foam::tmp<Foam::Field<Type> > Foam::BlockLduMatrix<Type>::residual
786 const Field<Type>& x,
790 return b + residual(x);
795 void Foam::BlockLduMatrix<Type>::negate()
812 // Do coupling coefficients
813 coupleUpper_.negate();
814 coupleLower_.negate();
818 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
822 void Foam::BlockLduMatrix<Type>::operator=(const BlockLduMatrix<Type>& A)
828 "void BlockLduMatrix<Type>::operator="
829 "(const BlockLduMatrix<Type>& A)"
830 ) << "attempted assignment to self"
831 << abort(FatalError);
859 // Copy interface data
860 interfaces_ = A.interfaces_;
861 coupleUpper_ = A.coupleUpper_;
862 coupleLower_ = A.coupleLower_;
865 fixedEqns_ = A.fixedEqns_;
870 void Foam::BlockLduMatrix<Type>::operator+=(const BlockLduMatrix<Type>& A)
880 upper() += A.upper();
882 if (this->asymmetric())
884 lower() += A.upper().transpose();
890 upper() += A.upper();
891 lower() += A.lower();
895 coupleUpper_ += A.coupleUpper_;
896 coupleLower_ += A.coupleLower_;
901 void Foam::BlockLduMatrix<Type>::operator-=(const BlockLduMatrix<Type>& A)
911 upper() -= A.upper();
913 if (this->asymmetric())
915 lower() -= A.upper().transpose();
921 upper() -= A.upper();
922 lower() -= A.lower();
926 coupleUpper_ -= A.coupleUpper_;
927 coupleLower_ -= A.coupleLower_;
932 void Foam::BlockLduMatrix<Type>::operator*=(const scalarField& sf)
934 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
935 typedef typename TypeCoeffField::linearTypeField linearTypeField;
936 typedef typename TypeCoeffField::squareTypeField squareTypeField;
938 //HJ Missing code: add coupling coefficients op*=
940 // IC - Complicated because we have to scale across the interfaces
941 // We may need to include this functionality in lduInterfaceField
942 // as additional initInterfaceScale and scaleInterface functions
951 TypeCoeffField& Upper = *upperPtr_;
953 const unallocLabelList& l = lduAddr().lowerAddr();
955 if (Upper.activeType() == blockCoeffBase::SCALAR)
957 scalarTypeField& activeUpper = Upper.asScalar();
959 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
961 activeUpper[coeffI] *= sf[l[coeffI]];
964 else if (Upper.activeType() == blockCoeffBase::LINEAR)
966 linearTypeField& activeUpper = Upper.asLinear();
968 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
970 activeUpper[coeffI] *= sf[l[coeffI]];
973 else if (Upper.activeType() == blockCoeffBase::SQUARE)
975 squareTypeField& activeUpper = Upper.asSquare();
977 for (register label coeffI = 0; coeffI < l.size(); coeffI++)
979 activeUpper[coeffI] *= sf[l[coeffI]];
986 TypeCoeffField& Lower = *lowerPtr_;
988 const unallocLabelList& u = lduAddr().upperAddr();
990 if (Lower.activeType() == blockCoeffBase::SCALAR)
992 scalarTypeField& activeLower = Lower.asScalar();
994 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
996 activeLower[coeffI] *= sf[u[coeffI]];
999 else if (Lower.activeType() == blockCoeffBase::LINEAR)
1001 linearTypeField& activeLower = Lower.asLinear();
1003 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
1005 activeLower[coeffI] *= sf[u[coeffI]];
1008 else if (Lower.activeType() == blockCoeffBase::SQUARE)
1010 squareTypeField& activeLower = Lower.asSquare();
1012 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
1014 activeLower[coeffI] *= sf[u[coeffI]];
1021 template<class Type>
1022 void Foam::BlockLduMatrix<Type>::operator*=(const scalar s)
1045 // ************************************************************************* //