Initial commit for version 2.0.x patch release
[OpenFOAM-2.0.x.git] / src / finiteVolume / fvMatrices / fvMatrix / fvMatrix.C
blobd5086f5951a330f37ef765ea4c71942d4d816cd3
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2004-2011 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
13     the Free Software Foundation, either version 3 of the License, or
14     (at your 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
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "volFields.H"
27 #include "surfaceFields.H"
28 #include "calculatedFvPatchFields.H"
29 #include "zeroGradientFvPatchFields.H"
30 #include "coupledFvPatchFields.H"
31 #include "UIndirectList.H"
33 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
35 template<class Type>
36 template<class Type2>
37 void Foam::fvMatrix<Type>::addToInternalField
39     const labelUList& addr,
40     const Field<Type2>& pf,
41     Field<Type2>& intf
42 ) const
44     if (addr.size() != pf.size())
45     {
46         FatalErrorIn
47         (
48             "fvMatrix<Type>::addToInternalField(const labelUList&, "
49             "const Field&, Field&)"
50         )   << "sizes of addressing and field are different"
51             << abort(FatalError);
52     }
54     forAll(addr, faceI)
55     {
56         intf[addr[faceI]] += pf[faceI];
57     }
61 template<class Type>
62 template<class Type2>
63 void Foam::fvMatrix<Type>::addToInternalField
65     const labelUList& addr,
66     const tmp<Field<Type2> >& tpf,
67     Field<Type2>& intf
68 ) const
70     addToInternalField(addr, tpf(), intf);
71     tpf.clear();
75 template<class Type>
76 template<class Type2>
77 void Foam::fvMatrix<Type>::subtractFromInternalField
79     const labelUList& addr,
80     const Field<Type2>& pf,
81     Field<Type2>& intf
82 ) const
84     if (addr.size() != pf.size())
85     {
86         FatalErrorIn
87         (
88             "fvMatrix<Type>::addToInternalField(const labelUList&, "
89             "const Field&, Field&)"
90         )   << "sizes of addressing and field are different"
91             << abort(FatalError);
92     }
94     forAll(addr, faceI)
95     {
96         intf[addr[faceI]] -= pf[faceI];
97     }
101 template<class Type>
102 template<class Type2>
103 void Foam::fvMatrix<Type>::subtractFromInternalField
105     const labelUList& addr,
106     const tmp<Field<Type2> >& tpf,
107     Field<Type2>& intf
108 ) const
110     subtractFromInternalField(addr, tpf(), intf);
111     tpf.clear();
115 template<class Type>
116 void Foam::fvMatrix<Type>::addBoundaryDiag
118     scalarField& diag,
119     const direction solveCmpt
120 ) const
122     forAll(internalCoeffs_, patchI)
123     {
124         addToInternalField
125         (
126             lduAddr().patchAddr(patchI),
127             internalCoeffs_[patchI].component(solveCmpt),
128             diag
129         );
130     }
134 template<class Type>
135 void Foam::fvMatrix<Type>::addCmptAvBoundaryDiag(scalarField& diag) const
137     forAll(internalCoeffs_, patchI)
138     {
139         addToInternalField
140         (
141             lduAddr().patchAddr(patchI),
142             cmptAv(internalCoeffs_[patchI]),
143             diag
144         );
145     }
149 template<class Type>
150 void Foam::fvMatrix<Type>::addBoundarySource
152     Field<Type>& source,
153     const bool couples
154 ) const
156     forAll(psi_.boundaryField(), patchI)
157     {
158         const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
159         const Field<Type>& pbc = boundaryCoeffs_[patchI];
161         if (!ptf.coupled())
162         {
163             addToInternalField(lduAddr().patchAddr(patchI), pbc, source);
164         }
165         else if (couples)
166         {
167             tmp<Field<Type> > tpnf = ptf.patchNeighbourField();
168             const Field<Type>& pnf = tpnf();
170             const labelUList& addr = lduAddr().patchAddr(patchI);
172             forAll(addr, facei)
173             {
174                 source[addr[facei]] += cmptMultiply(pbc[facei], pnf[facei]);
175             }
176         }
177     }
181 template<class Type>
182 template<template<class> class ListType>
183 void Foam::fvMatrix<Type>::setValuesFromList
185     const labelUList& cellLabels,
186     const ListType<Type>& values
189     const fvMesh& mesh = psi_.mesh();
191     const cellList& cells = mesh.cells();
192     const labelUList& own = mesh.owner();
193     const labelUList& nei = mesh.neighbour();
195     scalarField& Diag = diag();
196     Field<Type>& psi =
197         const_cast
198         <
199             GeometricField<Type, fvPatchField, volMesh>&
200         >(psi_).internalField();
202     forAll(cellLabels, i)
203     {
204         const label celli = cellLabels[i];
205         const Type& value = values[i];
207         psi[celli] = value;
208         source_[celli] = value*Diag[celli];
210         if (symmetric() || asymmetric())
211         {
212             const cell& c = cells[celli];
214             forAll(c, j)
215             {
216                 const label facei = c[j];
218                 if (mesh.isInternalFace(facei))
219                 {
220                     if (symmetric())
221                     {
222                         if (celli == own[facei])
223                         {
224                             source_[nei[facei]] -= upper()[facei]*value;
225                         }
226                         else
227                         {
228                             source_[own[facei]] -= upper()[facei]*value;
229                         }
231                         upper()[facei] = 0.0;
232                     }
233                     else
234                     {
235                         if (celli == own[facei])
236                         {
237                             source_[nei[facei]] -= lower()[facei]*value;
238                         }
239                         else
240                         {
241                             source_[own[facei]] -= upper()[facei]*value;
242                         }
244                         upper()[facei] = 0.0;
245                         lower()[facei] = 0.0;
246                     }
247                 }
248                 else
249                 {
250                     label patchi = mesh.boundaryMesh().whichPatch(facei);
252                     if (internalCoeffs_[patchi].size())
253                     {
254                         label patchFacei =
255                             mesh.boundaryMesh()[patchi].whichFace(facei);
257                         internalCoeffs_[patchi][patchFacei] =
258                             pTraits<Type>::zero;
260                         boundaryCoeffs_[patchi][patchFacei] =
261                             pTraits<Type>::zero;
262                     }
263                 }
264             }
265         }
266     }
270 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
272 template<class Type>
273 Foam::fvMatrix<Type>::fvMatrix
275     const GeometricField<Type, fvPatchField, volMesh>& psi,
276     const dimensionSet& ds
279     lduMatrix(psi.mesh()),
280     psi_(psi),
281     dimensions_(ds),
282     source_(psi.size(), pTraits<Type>::zero),
283     internalCoeffs_(psi.mesh().boundary().size()),
284     boundaryCoeffs_(psi.mesh().boundary().size()),
285     faceFluxCorrectionPtr_(NULL)
287     if (debug)
288     {
289         Info<< "fvMatrix<Type>(GeometricField<Type, fvPatchField, volMesh>&,"
290                " const dimensionSet&) : "
291                "constructing fvMatrix<Type> for field " << psi_.name()
292             << endl;
293     }
295     // Initialise coupling coefficients
296     forAll(psi.mesh().boundary(), patchI)
297     {
298         internalCoeffs_.set
299         (
300             patchI,
301             new Field<Type>
302             (
303                 psi.mesh().boundary()[patchI].size(),
304                 pTraits<Type>::zero
305             )
306         );
308         boundaryCoeffs_.set
309         (
310             patchI,
311             new Field<Type>
312             (
313                 psi.mesh().boundary()[patchI].size(),
314                 pTraits<Type>::zero
315             )
316         );
317     }
319     // Update the boundary coefficients of psi without changing its event No.
320     GeometricField<Type, fvPatchField, volMesh>& psiRef =
321        const_cast<GeometricField<Type, fvPatchField, volMesh>&>(psi_);
323     label currentStatePsi = psiRef.eventNo();
324     psiRef.boundaryField().updateCoeffs();
325     psiRef.eventNo() = currentStatePsi;
329 template<class Type>
330 Foam::fvMatrix<Type>::fvMatrix(const fvMatrix<Type>& fvm)
332     refCount(),
333     lduMatrix(fvm),
334     psi_(fvm.psi_),
335     dimensions_(fvm.dimensions_),
336     source_(fvm.source_),
337     internalCoeffs_(fvm.internalCoeffs_),
338     boundaryCoeffs_(fvm.boundaryCoeffs_),
339     faceFluxCorrectionPtr_(NULL)
341     if (debug)
342     {
343         Info<< "fvMatrix<Type>::fvMatrix(const fvMatrix<Type>&) : "
344             << "copying fvMatrix<Type> for field " << psi_.name()
345             << endl;
346     }
348     if (fvm.faceFluxCorrectionPtr_)
349     {
350         faceFluxCorrectionPtr_ = new
351         GeometricField<Type, fvsPatchField, surfaceMesh>
352         (
353             *(fvm.faceFluxCorrectionPtr_)
354         );
355     }
359 #ifdef ConstructFromTmp
360 template<class Type>
361 Foam::fvMatrix<Type>::fvMatrix(const tmp<fvMatrix<Type> >& tfvm)
363     refCount(),
364     lduMatrix
365     (
366         const_cast<fvMatrix<Type>&>(tfvm()),
367         tfvm.isTmp()
368     ),
369     psi_(tfvm().psi_),
370     dimensions_(tfvm().dimensions_),
371     source_
372     (
373         const_cast<fvMatrix<Type>&>(tfvm()).source_,
374         tfvm.isTmp()
375     ),
376     internalCoeffs_
377     (
378         const_cast<fvMatrix<Type>&>(tfvm()).internalCoeffs_,
379         tfvm.isTmp()
380     ),
381     boundaryCoeffs_
382     (
383         const_cast<fvMatrix<Type>&>(tfvm()).boundaryCoeffs_,
384         tfvm.isTmp()
385     ),
386     faceFluxCorrectionPtr_(NULL)
388     if (debug)
389     {
390         Info<< "fvMatrix<Type>::fvMatrix(const tmp<fvMatrix<Type> >&) : "
391             << "copying fvMatrix<Type> for field " << psi_.name()
392             << endl;
393     }
395     if (tfvm().faceFluxCorrectionPtr_)
396     {
397         if (tfvm.isTmp())
398         {
399             faceFluxCorrectionPtr_ = tfvm().faceFluxCorrectionPtr_;
400             tfvm().faceFluxCorrectionPtr_ = NULL;
401         }
402         else
403         {
404             faceFluxCorrectionPtr_ = new
405                 GeometricField<Type, fvsPatchField, surfaceMesh>
406                 (
407                     *(tfvm().faceFluxCorrectionPtr_)
408                 );
409         }
410     }
412     tfvm.clear();
414 #endif
417 template<class Type>
418 Foam::fvMatrix<Type>::fvMatrix
420     const GeometricField<Type, fvPatchField, volMesh>& psi,
421     Istream& is
424     lduMatrix(psi.mesh()),
425     psi_(psi),
426     dimensions_(is),
427     source_(is),
428     internalCoeffs_(psi.mesh().boundary().size()),
429     boundaryCoeffs_(psi.mesh().boundary().size()),
430     faceFluxCorrectionPtr_(NULL)
432     if (debug)
433     {
434         Info<< "fvMatrix<Type>"
435                "(GeometricField<Type, fvPatchField, volMesh>&, Istream&) : "
436                "constructing fvMatrix<Type> for field " << psi_.name()
437             << endl;
438     }
440     // Initialise coupling coefficients
441     forAll(psi.mesh().boundary(), patchI)
442     {
443         internalCoeffs_.set
444         (
445             patchI,
446             new Field<Type>
447             (
448                 psi.mesh().boundary()[patchI].size(),
449                 pTraits<Type>::zero
450             )
451         );
453         boundaryCoeffs_.set
454         (
455             patchI,
456             new Field<Type>
457             (
458                 psi.mesh().boundary()[patchI].size(),
459                 pTraits<Type>::zero
460             )
461         );
462     }
467 template<class Type>
468 Foam::fvMatrix<Type>::~fvMatrix()
470     if (debug)
471     {
472         Info<< "fvMatrix<Type>::~fvMatrix<Type>() : "
473             << "destroying fvMatrix<Type> for field " << psi_.name()
474             << endl;
475     }
477     if (faceFluxCorrectionPtr_)
478     {
479         delete faceFluxCorrectionPtr_;
480     }
484 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
486 template<class Type>
487 void Foam::fvMatrix<Type>::setValues
489     const labelUList& cellLabels,
490     const UList<Type>& values
493     this->setValuesFromList(cellLabels, values);
497 template<class Type>
498 void Foam::fvMatrix<Type>::setValues
500     const labelUList& cellLabels,
501     const UIndirectList<Type>& values
504     this->setValuesFromList(cellLabels, values);
508 template<class Type>
509 void Foam::fvMatrix<Type>::setReference
511     const label celli,
512     const Type& value,
513     const bool forceReference
516     if ((forceReference || psi_.needReference()) && celli >= 0)
517     {
518         source()[celli] += diag()[celli]*value;
519         diag()[celli] += diag()[celli];
520     }
524 template<class Type>
525 void Foam::fvMatrix<Type>::relax(const scalar alpha)
527     if (alpha <= 0)
528     {
529         return;
530     }
532     if (debug)
533     {
534         InfoIn("fvMatrix<Type>::relax(const scalar alpha)")
535             << "Relaxing " << psi_.name() << " by " << alpha
536             << endl;
537     }
539     Field<Type>& S = source();
540     scalarField& D = diag();
542     // Store the current unrelaxed diagonal for use in updating the source
543     scalarField D0(D);
545     // Calculate the sum-mag off-diagonal from the interior faces
546     scalarField sumOff(D.size(), 0.0);
547     sumMagOffDiag(sumOff);
549     // Handle the boundary contributions to the diagonal
550     forAll(psi_.boundaryField(), patchI)
551     {
552         const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
554         if (ptf.size())
555         {
556             const labelUList& pa = lduAddr().patchAddr(patchI);
557             Field<Type>& iCoeffs = internalCoeffs_[patchI];
559             if (ptf.coupled())
560             {
561                 const Field<Type>& pCoeffs = boundaryCoeffs_[patchI];
563                 // For coupled boundaries add the diagonal and
564                 // off-diagonal contributions
565                 forAll(pa, face)
566                 {
567                     D[pa[face]] += component(iCoeffs[face], 0);
568                     sumOff[pa[face]] += mag(component(pCoeffs[face], 0));
569                 }
570             }
571             else
572             {
573                 // For non-coupled boundaries subtract the diagonal
574                 // contribution off-diagonal sum which avoids having to remove
575                 // it from the diagonal later.
576                 // Also add the source contribution from the relaxation
577                 forAll(pa, face)
578                 {
579                     Type iCoeff0 = iCoeffs[face];
580                     iCoeffs[face] = cmptMag(iCoeffs[face]);
581                     sumOff[pa[face]] -= cmptMin(iCoeffs[face]);
582                     iCoeffs[face] /= alpha;
583                     S[pa[face]] +=
584                         cmptMultiply(iCoeffs[face] - iCoeff0, psi_[pa[face]]);
585                 }
586             }
587         }
588     }
590     // Ensure the matrix is diagonally dominant...
591     max(D, D, sumOff);
593     // ... then relax
594     D /= alpha;
596     // Now remove the diagonal contribution from coupled boundaries
597     forAll(psi_.boundaryField(), patchI)
598     {
599         const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
601         if (ptf.size())
602         {
603             const labelUList& pa = lduAddr().patchAddr(patchI);
604             Field<Type>& iCoeffs = internalCoeffs_[patchI];
606             if (ptf.coupled())
607             {
608                 forAll(pa, face)
609                 {
610                     D[pa[face]] -= component(iCoeffs[face], 0);
611                 }
612             }
613         }
614     }
616     // Finally add the relaxation contribution to the source.
617     S += (D - D0)*psi_.internalField();
621 template<class Type>
622 void Foam::fvMatrix<Type>::relax()
624     word name = psi_.select
625     (
626         psi_.mesh().data::template lookupOrDefault<bool>
627         ("finalIteration", false)
628     );
630     if (psi_.mesh().relax(name))
631     {
632         relax(psi_.mesh().relaxationFactor(name));
633     }
637 template<class Type>
638 void Foam::fvMatrix<Type>::boundaryManipulate
640     typename GeometricField<Type, fvPatchField, volMesh>::
641         GeometricBoundaryField& bFields
644     forAll(bFields, patchI)
645     {
646         bFields[patchI].manipulateMatrix(*this);
647     }
651 template<class Type>
652 Foam::tmp<Foam::scalarField> Foam::fvMatrix<Type>::D() const
654     tmp<scalarField> tdiag(new scalarField(diag()));
655     addCmptAvBoundaryDiag(tdiag());
656     return tdiag;
660 template<class Type>
661 Foam::tmp<Foam::Field<Type> > Foam::fvMatrix<Type>::DD() const
663     tmp<Field<Type> > tdiag(pTraits<Type>::one*diag());
665     forAll(psi_.boundaryField(), patchI)
666     {
667         const fvPatchField<Type>& ptf = psi_.boundaryField()[patchI];
669         if (!ptf.coupled() && ptf.size())
670         {
671             addToInternalField
672             (
673                 lduAddr().patchAddr(patchI),
674                 internalCoeffs_[patchI],
675                 tdiag()
676             );
677         }
678     }
680     return tdiag;
684 template<class Type>
685 Foam::tmp<Foam::volScalarField> Foam::fvMatrix<Type>::A() const
687     tmp<volScalarField> tAphi
688     (
689         new volScalarField
690         (
691             IOobject
692             (
693                 "A("+psi_.name()+')',
694                 psi_.instance(),
695                 psi_.mesh(),
696                 IOobject::NO_READ,
697                 IOobject::NO_WRITE
698             ),
699             psi_.mesh(),
700             dimensions_/psi_.dimensions()/dimVol,
701             zeroGradientFvPatchScalarField::typeName
702         )
703     );
705     tAphi().internalField() = D()/psi_.mesh().V();
706     tAphi().correctBoundaryConditions();
708     return tAphi;
712 template<class Type>
713 Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
714 Foam::fvMatrix<Type>::H() const
716     tmp<GeometricField<Type, fvPatchField, volMesh> > tHphi
717     (
718         new GeometricField<Type, fvPatchField, volMesh>
719         (
720             IOobject
721             (
722                 "H("+psi_.name()+')',
723                 psi_.instance(),
724                 psi_.mesh(),
725                 IOobject::NO_READ,
726                 IOobject::NO_WRITE
727             ),
728             psi_.mesh(),
729             dimensions_/dimVol,
730             zeroGradientFvPatchScalarField::typeName
731         )
732     );
733     GeometricField<Type, fvPatchField, volMesh>& Hphi = tHphi();
735     // Loop over field components
736     for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
737     {
738         scalarField psiCmpt(psi_.internalField().component(cmpt));
740         scalarField boundaryDiagCmpt(psi_.size(), 0.0);
741         addBoundaryDiag(boundaryDiagCmpt, cmpt);
742         boundaryDiagCmpt.negate();
743         addCmptAvBoundaryDiag(boundaryDiagCmpt);
745         Hphi.internalField().replace(cmpt, boundaryDiagCmpt*psiCmpt);
746     }
748     Hphi.internalField() += lduMatrix::H(psi_.internalField()) + source_;
749     addBoundarySource(Hphi.internalField());
751     Hphi.internalField() /= psi_.mesh().V();
752     Hphi.correctBoundaryConditions();
754     typename Type::labelType validComponents
755     (
756         pow
757         (
758             psi_.mesh().solutionD(),
759             pTraits<typename powProduct<Vector<label>, Type::rank>::type>::zero
760         )
761     );
763     for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
764     {
765         if (validComponents[cmpt] == -1)
766         {
767             Hphi.replace
768             (
769                 cmpt,
770                 dimensionedScalar("0", Hphi.dimensions(), 0.0)
771             );
772         }
773     }
775     return tHphi;
779 template<class Type>
780 Foam::tmp<Foam::volScalarField> Foam::fvMatrix<Type>::H1() const
782     tmp<volScalarField> tH1
783     (
784         new volScalarField
785         (
786             IOobject
787             (
788                 "H(1)",
789                 psi_.instance(),
790                 psi_.mesh(),
791                 IOobject::NO_READ,
792                 IOobject::NO_WRITE
793             ),
794             psi_.mesh(),
795             dimensions_/(dimVol*psi_.dimensions()),
796             zeroGradientFvPatchScalarField::typeName
797         )
798     );
799     volScalarField& H1_ = tH1();
801     // Loop over field components
802     /*
803     for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
804     {
805         scalarField psiCmpt(psi_.internalField().component(cmpt));
807         scalarField boundaryDiagCmpt(psi_.size(), 0.0);
808         addBoundaryDiag(boundaryDiagCmpt, cmpt);
809         boundaryDiagCmpt.negate();
810         addCmptAvBoundaryDiag(boundaryDiagCmpt);
812         H1_.internalField().replace(cmpt, boundaryDiagCmpt);
813     }
815     H1_.internalField() += lduMatrix::H1();
816     */
818     H1_.internalField() = lduMatrix::H1();
820     H1_.internalField() /= psi_.mesh().V();
821     H1_.correctBoundaryConditions();
823     return tH1;
827 template<class Type>
828 Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh> >
829 Foam::fvMatrix<Type>::
830 flux() const
832     if (!psi_.mesh().fluxRequired(psi_.name()))
833     {
834         FatalErrorIn("fvMatrix<Type>::flux()")
835             << "flux requested but " << psi_.name()
836             << " not specified in the fluxRequired sub-dictionary"
837                " of fvSchemes."
838             << abort(FatalError);
839     }
841     // construct GeometricField<Type, fvsPatchField, surfaceMesh>
842     tmp<GeometricField<Type, fvsPatchField, surfaceMesh> > tfieldFlux
843     (
844         new GeometricField<Type, fvsPatchField, surfaceMesh>
845         (
846             IOobject
847             (
848                 "flux("+psi_.name()+')',
849                 psi_.instance(),
850                 psi_.mesh(),
851                 IOobject::NO_READ,
852                 IOobject::NO_WRITE
853             ),
854             psi_.mesh(),
855             dimensions()
856         )
857     );
858     GeometricField<Type, fvsPatchField, surfaceMesh>& fieldFlux = tfieldFlux();
860     for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
861     {
862         fieldFlux.internalField().replace
863         (
864             cmpt,
865             lduMatrix::faceH(psi_.internalField().component(cmpt))
866         );
867     }
869     FieldField<Field, Type> InternalContrib = internalCoeffs_;
871     forAll(InternalContrib, patchI)
872     {
873         InternalContrib[patchI] =
874             cmptMultiply
875             (
876                 InternalContrib[patchI],
877                 psi_.boundaryField()[patchI].patchInternalField()
878             );
879     }
881     FieldField<Field, Type> NeighbourContrib = boundaryCoeffs_;
883     forAll(NeighbourContrib, patchI)
884     {
885         if (psi_.boundaryField()[patchI].coupled())
886         {
887             NeighbourContrib[patchI] =
888                 cmptMultiply
889                 (
890                     NeighbourContrib[patchI],
891                     psi_.boundaryField()[patchI].patchNeighbourField()
892                 );
893         }
894     }
896     forAll(fieldFlux.boundaryField(), patchI)
897     {
898         fieldFlux.boundaryField()[patchI] =
899             InternalContrib[patchI] - NeighbourContrib[patchI];
900     }
902     if (faceFluxCorrectionPtr_)
903     {
904         fieldFlux += *faceFluxCorrectionPtr_;
905     }
907     return tfieldFlux;
911 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
913 template<class Type>
914 void Foam::fvMatrix<Type>::operator=(const fvMatrix<Type>& fvmv)
916     if (this == &fvmv)
917     {
918         FatalErrorIn("fvMatrix<Type>::operator=(const fvMatrix<Type>&)")
919             << "attempted assignment to self"
920             << abort(FatalError);
921     }
923     if (&psi_ != &(fvmv.psi_))
924     {
925         FatalErrorIn("fvMatrix<Type>::operator=(const fvMatrix<Type>&)")
926             << "different fields"
927             << abort(FatalError);
928     }
930     lduMatrix::operator=(fvmv);
931     source_ = fvmv.source_;
932     internalCoeffs_ = fvmv.internalCoeffs_;
933     boundaryCoeffs_ = fvmv.boundaryCoeffs_;
935     if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
936     {
937         *faceFluxCorrectionPtr_ = *fvmv.faceFluxCorrectionPtr_;
938     }
939     else if (fvmv.faceFluxCorrectionPtr_)
940     {
941         faceFluxCorrectionPtr_ =
942             new GeometricField<Type, fvsPatchField, surfaceMesh>
943         (*fvmv.faceFluxCorrectionPtr_);
944     }
948 template<class Type>
949 void Foam::fvMatrix<Type>::operator=(const tmp<fvMatrix<Type> >& tfvmv)
951     operator=(tfvmv());
952     tfvmv.clear();
956 template<class Type>
957 void Foam::fvMatrix<Type>::negate()
959     lduMatrix::negate();
960     source_.negate();
961     internalCoeffs_.negate();
962     boundaryCoeffs_.negate();
964     if (faceFluxCorrectionPtr_)
965     {
966         faceFluxCorrectionPtr_->negate();
967     }
971 template<class Type>
972 void Foam::fvMatrix<Type>::operator+=(const fvMatrix<Type>& fvmv)
974     checkMethod(*this, fvmv, "+=");
976     dimensions_ += fvmv.dimensions_;
977     lduMatrix::operator+=(fvmv);
978     source_ += fvmv.source_;
979     internalCoeffs_ += fvmv.internalCoeffs_;
980     boundaryCoeffs_ += fvmv.boundaryCoeffs_;
982     if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
983     {
984         *faceFluxCorrectionPtr_ += *fvmv.faceFluxCorrectionPtr_;
985     }
986     else if (fvmv.faceFluxCorrectionPtr_)
987     {
988         faceFluxCorrectionPtr_ = new
989         GeometricField<Type, fvsPatchField, surfaceMesh>
990         (
991             *fvmv.faceFluxCorrectionPtr_
992         );
993     }
997 template<class Type>
998 void Foam::fvMatrix<Type>::operator+=(const tmp<fvMatrix<Type> >& tfvmv)
1000     operator+=(tfvmv());
1001     tfvmv.clear();
1005 template<class Type>
1006 void Foam::fvMatrix<Type>::operator-=(const fvMatrix<Type>& fvmv)
1008     checkMethod(*this, fvmv, "+=");
1010     dimensions_ -= fvmv.dimensions_;
1011     lduMatrix::operator-=(fvmv);
1012     source_ -= fvmv.source_;
1013     internalCoeffs_ -= fvmv.internalCoeffs_;
1014     boundaryCoeffs_ -= fvmv.boundaryCoeffs_;
1016     if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
1017     {
1018         *faceFluxCorrectionPtr_ -= *fvmv.faceFluxCorrectionPtr_;
1019     }
1020     else if (fvmv.faceFluxCorrectionPtr_)
1021     {
1022         faceFluxCorrectionPtr_ =
1023             new GeometricField<Type, fvsPatchField, surfaceMesh>
1024         (-*fvmv.faceFluxCorrectionPtr_);
1025     }
1029 template<class Type>
1030 void Foam::fvMatrix<Type>::operator-=(const tmp<fvMatrix<Type> >& tfvmv)
1032     operator-=(tfvmv());
1033     tfvmv.clear();
1037 template<class Type>
1038 void Foam::fvMatrix<Type>::operator+=
1040     const DimensionedField<Type, volMesh>& su
1043     checkMethod(*this, su, "+=");
1044     source() -= su.mesh().V()*su.field();
1048 template<class Type>
1049 void Foam::fvMatrix<Type>::operator+=
1051     const tmp<DimensionedField<Type, volMesh> >& tsu
1054     operator+=(tsu());
1055     tsu.clear();
1059 template<class Type>
1060 void Foam::fvMatrix<Type>::operator+=
1062     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu
1065     operator+=(tsu());
1066     tsu.clear();
1070 template<class Type>
1071 void Foam::fvMatrix<Type>::operator-=
1073     const DimensionedField<Type, volMesh>& su
1076     checkMethod(*this, su, "-=");
1077     source() += su.mesh().V()*su.field();
1081 template<class Type>
1082 void Foam::fvMatrix<Type>::operator-=
1084     const tmp<DimensionedField<Type, volMesh> >& tsu
1087     operator-=(tsu());
1088     tsu.clear();
1092 template<class Type>
1093 void Foam::fvMatrix<Type>::operator-=
1095     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu
1098     operator-=(tsu());
1099     tsu.clear();
1103 template<class Type>
1104 void Foam::fvMatrix<Type>::operator+=
1106     const dimensioned<Type>& su
1109     source() -= psi().mesh().V()*su;
1113 template<class Type>
1114 void Foam::fvMatrix<Type>::operator-=
1116     const dimensioned<Type>& su
1119     source() += psi().mesh().V()*su;
1123 template<class Type>
1124 void Foam::fvMatrix<Type>::operator+=
1126     const zero&
1131 template<class Type>
1132 void Foam::fvMatrix<Type>::operator-=
1134     const zero&
1139 template<class Type>
1140 void Foam::fvMatrix<Type>::operator*=
1142     const DimensionedField<scalar, volMesh>& dsf
1145     dimensions_ *= dsf.dimensions();
1146     lduMatrix::operator*=(dsf.field());
1147     source_ *= dsf.field();
1149     forAll(boundaryCoeffs_, patchI)
1150     {
1151         scalarField psf
1152         (
1153             dsf.mesh().boundary()[patchI].patchInternalField(dsf.field())
1154         );
1156         internalCoeffs_[patchI] *= psf;
1157         boundaryCoeffs_[patchI] *= psf;
1158     }
1160     if (faceFluxCorrectionPtr_)
1161     {
1162         FatalErrorIn
1163         (
1164             "fvMatrix<Type>::operator*="
1165             "(const DimensionedField<scalar, volMesh>&)"
1166         )   << "cannot scale a matrix containing a faceFluxCorrection"
1167             << abort(FatalError);
1168     }
1172 template<class Type>
1173 void Foam::fvMatrix<Type>::operator*=
1175     const tmp<DimensionedField<scalar, volMesh> >& tdsf
1178     operator*=(tdsf());
1179     tdsf.clear();
1183 template<class Type>
1184 void Foam::fvMatrix<Type>::operator*=
1186     const volScalarField& vsf
1189     dimensions_ *= vsf.dimensions();
1190     lduMatrix::operator*=(vsf.field());
1191     source_ *= vsf.field();
1193     forAll(vsf.boundaryField(), patchI)
1194     {
1195         const fvPatchScalarField& psf = vsf.boundaryField()[patchI];
1197         if (psf.coupled())
1198         {
1199             internalCoeffs_[patchI] *= psf.patchInternalField();
1200             boundaryCoeffs_[patchI] *= psf.patchNeighbourField();
1201         }
1202         else
1203         {
1204             internalCoeffs_[patchI] *= psf.patchInternalField();
1205             boundaryCoeffs_[patchI] *= psf;
1206         }
1207     }
1209     if (faceFluxCorrectionPtr_)
1210     {
1211         FatalErrorIn
1212         (
1213             "fvMatrix<Type>::operator*="
1214             "(const DimensionedField<scalar, volMesh>&)"
1215         )   << "cannot scale a matrix containing a faceFluxCorrection"
1216             << abort(FatalError);
1217     }
1220 template<class Type>
1221 void Foam::fvMatrix<Type>::operator*=
1223     const tmp<volScalarField>& tvsf
1226     operator*=(tvsf());
1227     tvsf.clear();
1231 template<class Type>
1232 void Foam::fvMatrix<Type>::operator*=
1234     const dimensioned<scalar>& ds
1237     dimensions_ *= ds.dimensions();
1238     lduMatrix::operator*=(ds.value());
1239     source_ *= ds.value();
1240     internalCoeffs_ *= ds.value();
1241     boundaryCoeffs_ *= ds.value();
1243     if (faceFluxCorrectionPtr_)
1244     {
1245         *faceFluxCorrectionPtr_ *= ds.value();
1246     }
1250 // * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
1252 template<class Type>
1253 void Foam::checkMethod
1255     const fvMatrix<Type>& fvm1,
1256     const fvMatrix<Type>& fvm2,
1257     const char* op
1260     if (&fvm1.psi() != &fvm2.psi())
1261     {
1262         FatalErrorIn
1263         (
1264             "checkMethod(const fvMatrix<Type>&, const fvMatrix<Type>&)"
1265         )   << "incompatible fields for operation "
1266             << endl << "    "
1267             << "[" << fvm1.psi().name() << "] "
1268             << op
1269             << " [" << fvm2.psi().name() << "]"
1270             << abort(FatalError);
1271     }
1273     if (dimensionSet::debug && fvm1.dimensions() != fvm2.dimensions())
1274     {
1275         FatalErrorIn
1276         (
1277             "checkMethod(const fvMatrix<Type>&, const fvMatrix<Type>&)"
1278         )   << "incompatible dimensions for operation "
1279             << endl << "    "
1280             << "[" << fvm1.psi().name() << fvm1.dimensions()/dimVolume << " ] "
1281             << op
1282             << " [" << fvm2.psi().name() << fvm2.dimensions()/dimVolume << " ]"
1283             << abort(FatalError);
1284     }
1288 template<class Type>
1289 void Foam::checkMethod
1291     const fvMatrix<Type>& fvm,
1292     const DimensionedField<Type, volMesh>& df,
1293     const char* op
1296     if (dimensionSet::debug && fvm.dimensions()/dimVolume != df.dimensions())
1297     {
1298         FatalErrorIn
1299         (
1300             "checkMethod(const fvMatrix<Type>&, const GeometricField<Type, "
1301             "fvPatchField, volMesh>&)"
1302         )   <<  "incompatible dimensions for operation "
1303             << endl << "    "
1304             << "[" << fvm.psi().name() << fvm.dimensions()/dimVolume << " ] "
1305             << op
1306             << " [" << df.name() << df.dimensions() << " ]"
1307             << abort(FatalError);
1308     }
1312 template<class Type>
1313 void Foam::checkMethod
1315     const fvMatrix<Type>& fvm,
1316     const dimensioned<Type>& dt,
1317     const char* op
1320     if (dimensionSet::debug && fvm.dimensions()/dimVolume != dt.dimensions())
1321     {
1322         FatalErrorIn
1323         (
1324             "checkMethod(const fvMatrix<Type>&, const dimensioned<Type>&)"
1325         )   << "incompatible dimensions for operation "
1326             << endl << "    "
1327             << "[" << fvm.psi().name() << fvm.dimensions()/dimVolume << " ] "
1328             << op
1329             << " [" << dt.name() << dt.dimensions() << " ]"
1330             << abort(FatalError);
1331     }
1335 template<class Type>
1336 Foam::lduMatrix::solverPerformance Foam::solve
1338     fvMatrix<Type>& fvm,
1339     const dictionary& solverControls
1342     return fvm.solve(solverControls);
1345 template<class Type>
1346 Foam::lduMatrix::solverPerformance Foam::solve
1348     const tmp<fvMatrix<Type> >& tfvm,
1349     const dictionary& solverControls
1352     lduMatrix::solverPerformance solverPerf =
1353         const_cast<fvMatrix<Type>&>(tfvm()).solve(solverControls);
1355     tfvm.clear();
1357     return solverPerf;
1361 template<class Type>
1362 Foam::lduMatrix::solverPerformance Foam::solve(fvMatrix<Type>& fvm)
1364     return fvm.solve();
1367 template<class Type>
1368 Foam::lduMatrix::solverPerformance Foam::solve(const tmp<fvMatrix<Type> >& tfvm)
1370     lduMatrix::solverPerformance solverPerf =
1371         const_cast<fvMatrix<Type>&>(tfvm()).solve();
1373     tfvm.clear();
1375     return solverPerf;
1379 template<class Type>
1380 Foam::tmp<Foam::fvMatrix<Type> > Foam::correction
1382     const fvMatrix<Type>& A
1385     tmp<Foam::fvMatrix<Type> > tAcorr = A - (A & A.psi());
1387     if
1388     (
1389         (A.hasUpper() || A.hasLower())
1390      && A.psi().mesh().fluxRequired(A.psi().name())
1391     )
1392     {
1393         tAcorr().faceFluxCorrectionPtr() = (-A.flux()).ptr();
1394     }
1396     return tAcorr;
1400 template<class Type>
1401 Foam::tmp<Foam::fvMatrix<Type> > Foam::correction
1403     const tmp<fvMatrix<Type> >& tA
1406     tmp<Foam::fvMatrix<Type> > tAcorr = tA - (tA() & tA().psi());
1408     // Note the matrix coefficients are still that of matrix A
1409     const fvMatrix<Type>& A = tAcorr();
1411     if
1412     (
1413         (A.hasUpper() || A.hasLower())
1414      && A.psi().mesh().fluxRequired(A.psi().name())
1415     )
1416     {
1417         tAcorr().faceFluxCorrectionPtr() = (-A.flux()).ptr();
1418     }
1420     return tAcorr;
1424 // * * * * * * * * * * * * * * * Global Operators  * * * * * * * * * * * * * //
1426 template<class Type>
1427 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1429     const fvMatrix<Type>& A,
1430     const fvMatrix<Type>& B
1433     checkMethod(A, B, "==");
1434     return (A - B);
1437 template<class Type>
1438 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1440     const tmp<fvMatrix<Type> >& tA,
1441     const fvMatrix<Type>& B
1444     checkMethod(tA(), B, "==");
1445     return (tA - B);
1448 template<class Type>
1449 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1451     const fvMatrix<Type>& A,
1452     const tmp<fvMatrix<Type> >& tB
1455     checkMethod(A, tB(), "==");
1456     return (A - tB);
1459 template<class Type>
1460 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1462     const tmp<fvMatrix<Type> >& tA,
1463     const tmp<fvMatrix<Type> >& tB
1466     checkMethod(tA(), tB(), "==");
1467     return (tA - tB);
1470 template<class Type>
1471 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1473     const fvMatrix<Type>& A,
1474     const DimensionedField<Type, volMesh>& su
1477     checkMethod(A, su, "==");
1478     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1479     tC().source() += su.mesh().V()*su.field();
1480     return tC;
1483 template<class Type>
1484 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1486     const fvMatrix<Type>& A,
1487     const tmp<DimensionedField<Type, volMesh> >& tsu
1490     checkMethod(A, tsu(), "==");
1491     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1492     tC().source() += tsu().mesh().V()*tsu().field();
1493     tsu.clear();
1494     return tC;
1497 template<class Type>
1498 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1500     const fvMatrix<Type>& A,
1501     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu
1504     checkMethod(A, tsu(), "==");
1505     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1506     tC().source() += tsu().mesh().V()*tsu().internalField();
1507     tsu.clear();
1508     return tC;
1511 template<class Type>
1512 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1514     const tmp<fvMatrix<Type> >& tA,
1515     const DimensionedField<Type, volMesh>& su
1518     checkMethod(tA(), su, "==");
1519     tmp<fvMatrix<Type> > tC(tA.ptr());
1520     tC().source() += su.mesh().V()*su.field();
1521     return tC;
1524 template<class Type>
1525 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1527     const tmp<fvMatrix<Type> >& tA,
1528     const tmp<DimensionedField<Type, volMesh> >& tsu
1531     checkMethod(tA(), tsu(), "==");
1532     tmp<fvMatrix<Type> > tC(tA.ptr());
1533     tC().source() += tsu().mesh().V()*tsu().field();
1534     tsu.clear();
1535     return tC;
1538 template<class Type>
1539 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1541     const tmp<fvMatrix<Type> >& tA,
1542     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu
1545     checkMethod(tA(), tsu(), "==");
1546     tmp<fvMatrix<Type> > tC(tA.ptr());
1547     tC().source() += tsu().mesh().V()*tsu().internalField();
1548     tsu.clear();
1549     return tC;
1552 template<class Type>
1553 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1555     const fvMatrix<Type>& A,
1556     const dimensioned<Type>& su
1559     checkMethod(A, su, "==");
1560     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1561     tC().source() += A.psi().mesh().V()*su.value();
1562     return tC;
1565 template<class Type>
1566 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1568     const tmp<fvMatrix<Type> >& tA,
1569     const dimensioned<Type>& su
1572     checkMethod(tA(), su, "==");
1573     tmp<fvMatrix<Type> > tC(tA.ptr());
1574     tC().source() += tC().psi().mesh().V()*su.value();
1575     return tC;
1578 template<class Type>
1579 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1581     const fvMatrix<Type>& A,
1582     const zero&
1585     return A;
1589 template<class Type>
1590 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator==
1592     const tmp<fvMatrix<Type> >& tA,
1593     const zero&
1596     return tA;
1600 template<class Type>
1601 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1603     const fvMatrix<Type>& A
1606     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1607     tC().negate();
1608     return tC;
1611 template<class Type>
1612 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1614     const tmp<fvMatrix<Type> >& tA
1617     tmp<fvMatrix<Type> > tC(tA.ptr());
1618     tC().negate();
1619     return tC;
1623 template<class Type>
1624 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1626     const fvMatrix<Type>& A,
1627     const fvMatrix<Type>& B
1630     checkMethod(A, B, "+");
1631     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1632     tC() += B;
1633     return tC;
1636 template<class Type>
1637 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1639     const tmp<fvMatrix<Type> >& tA,
1640     const fvMatrix<Type>& B
1643     checkMethod(tA(), B, "+");
1644     tmp<fvMatrix<Type> > tC(tA.ptr());
1645     tC() += B;
1646     return tC;
1649 template<class Type>
1650 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1652     const fvMatrix<Type>& A,
1653     const tmp<fvMatrix<Type> >& tB
1656     checkMethod(A, tB(), "+");
1657     tmp<fvMatrix<Type> > tC(tB.ptr());
1658     tC() += A;
1659     return tC;
1662 template<class Type>
1663 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1665     const tmp<fvMatrix<Type> >& tA,
1666     const tmp<fvMatrix<Type> >& tB
1669     checkMethod(tA(), tB(), "+");
1670     tmp<fvMatrix<Type> > tC(tA.ptr());
1671     tC() += tB();
1672     tB.clear();
1673     return tC;
1676 template<class Type>
1677 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1679     const fvMatrix<Type>& A,
1680     const DimensionedField<Type, volMesh>& su
1683     checkMethod(A, su, "+");
1684     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1685     tC().source() -= su.mesh().V()*su.field();
1686     return tC;
1689 template<class Type>
1690 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1692     const fvMatrix<Type>& A,
1693     const tmp<DimensionedField<Type, volMesh> >& tsu
1696     checkMethod(A, tsu(), "+");
1697     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1698     tC().source() -= tsu().mesh().V()*tsu().field();
1699     tsu.clear();
1700     return tC;
1703 template<class Type>
1704 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1706     const fvMatrix<Type>& A,
1707     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu
1710     checkMethod(A, tsu(), "+");
1711     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1712     tC().source() -= tsu().mesh().V()*tsu().internalField();
1713     tsu.clear();
1714     return tC;
1717 template<class Type>
1718 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1720     const tmp<fvMatrix<Type> >& tA,
1721     const DimensionedField<Type, volMesh>& su
1724     checkMethod(tA(), su, "+");
1725     tmp<fvMatrix<Type> > tC(tA.ptr());
1726     tC().source() -= su.mesh().V()*su.field();
1727     return tC;
1730 template<class Type>
1731 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1733     const tmp<fvMatrix<Type> >& tA,
1734     const tmp<DimensionedField<Type, volMesh> >& tsu
1737     checkMethod(tA(), tsu(), "+");
1738     tmp<fvMatrix<Type> > tC(tA.ptr());
1739     tC().source() -= tsu().mesh().V()*tsu().field();
1740     tsu.clear();
1741     return tC;
1744 template<class Type>
1745 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1747     const tmp<fvMatrix<Type> >& tA,
1748     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu
1751     checkMethod(tA(), tsu(), "+");
1752     tmp<fvMatrix<Type> > tC(tA.ptr());
1753     tC().source() -= tsu().mesh().V()*tsu().internalField();
1754     tsu.clear();
1755     return tC;
1758 template<class Type>
1759 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1761     const DimensionedField<Type, volMesh>& su,
1762     const fvMatrix<Type>& A
1765     checkMethod(A, su, "+");
1766     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1767     tC().source() -= su.mesh().V()*su.field();
1768     return tC;
1771 template<class Type>
1772 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1774     const tmp<DimensionedField<Type, volMesh> >& tsu,
1775     const fvMatrix<Type>& A
1778     checkMethod(A, tsu(), "+");
1779     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1780     tC().source() -= tsu().mesh().V()*tsu().field();
1781     tsu.clear();
1782     return tC;
1785 template<class Type>
1786 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1788     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu,
1789     const fvMatrix<Type>& A
1792     checkMethod(A, tsu(), "+");
1793     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1794     tC().source() -= tsu().mesh().V()*tsu().internalField();
1795     tsu.clear();
1796     return tC;
1799 template<class Type>
1800 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1802     const DimensionedField<Type, volMesh>& su,
1803     const tmp<fvMatrix<Type> >& tA
1806     checkMethod(tA(), su, "+");
1807     tmp<fvMatrix<Type> > tC(tA.ptr());
1808     tC().source() -= su.mesh().V()*su.field();
1809     return tC;
1812 template<class Type>
1813 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1815     const tmp<DimensionedField<Type, volMesh> >& tsu,
1816     const tmp<fvMatrix<Type> >& tA
1819     checkMethod(tA(), tsu(), "+");
1820     tmp<fvMatrix<Type> > tC(tA.ptr());
1821     tC().source() -= tsu().mesh().V()*tsu().field();
1822     tsu.clear();
1823     return tC;
1826 template<class Type>
1827 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
1829     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu,
1830     const tmp<fvMatrix<Type> >& tA
1833     checkMethod(tA(), tsu(), "+");
1834     tmp<fvMatrix<Type> > tC(tA.ptr());
1835     tC().source() -= tsu().mesh().V()*tsu().internalField();
1836     tsu.clear();
1837     return tC;
1841 template<class Type>
1842 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1844     const fvMatrix<Type>& A,
1845     const fvMatrix<Type>& B
1848     checkMethod(A, B, "-");
1849     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1850     tC() -= B;
1851     return tC;
1854 template<class Type>
1855 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1857     const tmp<fvMatrix<Type> >& tA,
1858     const fvMatrix<Type>& B
1861     checkMethod(tA(), B, "-");
1862     tmp<fvMatrix<Type> > tC(tA.ptr());
1863     tC() -= B;
1864     return tC;
1867 template<class Type>
1868 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1870     const fvMatrix<Type>& A,
1871     const tmp<fvMatrix<Type> >& tB
1874     checkMethod(A, tB(), "-");
1875     tmp<fvMatrix<Type> > tC(tB.ptr());
1876     tC() -= A;
1877     tC().negate();
1878     return tC;
1881 template<class Type>
1882 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1884     const tmp<fvMatrix<Type> >& tA,
1885     const tmp<fvMatrix<Type> >& tB
1888     checkMethod(tA(), tB(), "-");
1889     tmp<fvMatrix<Type> > tC(tA.ptr());
1890     tC() -= tB();
1891     tB.clear();
1892     return tC;
1895 template<class Type>
1896 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1898     const fvMatrix<Type>& A,
1899     const DimensionedField<Type, volMesh>& su
1902     checkMethod(A, su, "-");
1903     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1904     tC().source() += su.mesh().V()*su.field();
1905     return tC;
1908 template<class Type>
1909 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1911     const fvMatrix<Type>& A,
1912     const tmp<DimensionedField<Type, volMesh> >& tsu
1915     checkMethod(A, tsu(), "-");
1916     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1917     tC().source() += tsu().mesh().V()*tsu().field();
1918     tsu.clear();
1919     return tC;
1922 template<class Type>
1923 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1925     const fvMatrix<Type>& A,
1926     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu
1929     checkMethod(A, tsu(), "-");
1930     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1931     tC().source() += tsu().mesh().V()*tsu().internalField();
1932     tsu.clear();
1933     return tC;
1936 template<class Type>
1937 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1939     const tmp<fvMatrix<Type> >& tA,
1940     const DimensionedField<Type, volMesh>& su
1943     checkMethod(tA(), su, "-");
1944     tmp<fvMatrix<Type> > tC(tA.ptr());
1945     tC().source() += su.mesh().V()*su.field();
1946     return tC;
1949 template<class Type>
1950 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1952     const tmp<fvMatrix<Type> >& tA,
1953     const tmp<DimensionedField<Type, volMesh> >& tsu
1956     checkMethod(tA(), tsu(), "-");
1957     tmp<fvMatrix<Type> > tC(tA.ptr());
1958     tC().source() += tsu().mesh().V()*tsu().field();
1959     tsu.clear();
1960     return tC;
1963 template<class Type>
1964 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1966     const tmp<fvMatrix<Type> >& tA,
1967     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu
1970     checkMethod(tA(), tsu(), "-");
1971     tmp<fvMatrix<Type> > tC(tA.ptr());
1972     tC().source() += tsu().mesh().V()*tsu().internalField();
1973     tsu.clear();
1974     return tC;
1977 template<class Type>
1978 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1980     const DimensionedField<Type, volMesh>& su,
1981     const fvMatrix<Type>& A
1984     checkMethod(A, su, "-");
1985     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
1986     tC().negate();
1987     tC().source() -= su.mesh().V()*su.field();
1988     return tC;
1991 template<class Type>
1992 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
1994     const tmp<DimensionedField<Type, volMesh> >& tsu,
1995     const fvMatrix<Type>& A
1998     checkMethod(A, tsu(), "-");
1999     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
2000     tC().negate();
2001     tC().source() -= tsu().mesh().V()*tsu().field();
2002     tsu.clear();
2003     return tC;
2006 template<class Type>
2007 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
2009     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu,
2010     const fvMatrix<Type>& A
2013     checkMethod(A, tsu(), "-");
2014     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
2015     tC().negate();
2016     tC().source() -= tsu().mesh().V()*tsu().internalField();
2017     tsu.clear();
2018     return tC;
2021 template<class Type>
2022 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
2024     const DimensionedField<Type, volMesh>& su,
2025     const tmp<fvMatrix<Type> >& tA
2028     checkMethod(tA(), su, "-");
2029     tmp<fvMatrix<Type> > tC(tA.ptr());
2030     tC().negate();
2031     tC().source() -= su.mesh().V()*su.field();
2032     return tC;
2035 template<class Type>
2036 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
2038     const tmp<DimensionedField<Type, volMesh> >& tsu,
2039     const tmp<fvMatrix<Type> >& tA
2042     checkMethod(tA(), tsu(), "-");
2043     tmp<fvMatrix<Type> > tC(tA.ptr());
2044     tC().negate();
2045     tC().source() -= tsu().mesh().V()*tsu().field();
2046     tsu.clear();
2047     return tC;
2050 template<class Type>
2051 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
2053     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tsu,
2054     const tmp<fvMatrix<Type> >& tA
2057     checkMethod(tA(), tsu(), "-");
2058     tmp<fvMatrix<Type> > tC(tA.ptr());
2059     tC().negate();
2060     tC().source() -= tsu().mesh().V()*tsu().internalField();
2061     tsu.clear();
2062     return tC;
2065 template<class Type>
2066 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
2068     const fvMatrix<Type>& A,
2069     const dimensioned<Type>& su
2072     checkMethod(A, su, "+");
2073     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
2074     tC().source() -= su.value()*A.psi().mesh().V();
2075     return tC;
2078 template<class Type>
2079 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
2081     const tmp<fvMatrix<Type> >& tA,
2082     const dimensioned<Type>& su
2085     checkMethod(tA(), su, "+");
2086     tmp<fvMatrix<Type> > tC(tA.ptr());
2087     tC().source() -= su.value()*tC().psi().mesh().V();
2088     return tC;
2091 template<class Type>
2092 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
2094     const dimensioned<Type>& su,
2095     const fvMatrix<Type>& A
2098     checkMethod(A, su, "+");
2099     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
2100     tC().source() -= su.value()*A.psi().mesh().V();
2101     return tC;
2104 template<class Type>
2105 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator+
2107     const dimensioned<Type>& su,
2108     const tmp<fvMatrix<Type> >& tA
2111     checkMethod(tA(), su, "+");
2112     tmp<fvMatrix<Type> > tC(tA.ptr());
2113     tC().source() -= su.value()*tC().psi().mesh().V();
2114     return tC;
2117 template<class Type>
2118 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
2120     const fvMatrix<Type>& A,
2121     const dimensioned<Type>& su
2124     checkMethod(A, su, "-");
2125     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
2126     tC().source() += su.value()*tC().psi().mesh().V();
2127     return tC;
2130 template<class Type>
2131 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
2133     const tmp<fvMatrix<Type> >& tA,
2134     const dimensioned<Type>& su
2137     checkMethod(tA(), su, "-");
2138     tmp<fvMatrix<Type> > tC(tA.ptr());
2139     tC().source() += su.value()*tC().psi().mesh().V();
2140     return tC;
2143 template<class Type>
2144 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
2146     const dimensioned<Type>& su,
2147     const fvMatrix<Type>& A
2150     checkMethod(A, su, "-");
2151     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
2152     tC().negate();
2153     tC().source() -= su.value()*A.psi().mesh().V();
2154     return tC;
2157 template<class Type>
2158 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator-
2160     const dimensioned<Type>& su,
2161     const tmp<fvMatrix<Type> >& tA
2164     checkMethod(tA(), su, "-");
2165     tmp<fvMatrix<Type> > tC(tA.ptr());
2166     tC().negate();
2167     tC().source() -= su.value()*tC().psi().mesh().V();
2168     return tC;
2172 template<class Type>
2173 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator*
2175     const DimensionedField<scalar, volMesh>& dsf,
2176     const fvMatrix<Type>& A
2179     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
2180     tC() *= dsf;
2181     return tC;
2184 template<class Type>
2185 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator*
2187     const tmp< DimensionedField<scalar, volMesh> >& tdsf,
2188     const fvMatrix<Type>& A
2191     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
2192     tC() *= tdsf;
2193     return tC;
2196 template<class Type>
2197 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator*
2199     const tmp<volScalarField>& tvsf,
2200     const fvMatrix<Type>& A
2203     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
2204     tC() *= tvsf;
2205     return tC;
2208 template<class Type>
2209 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator*
2211     const DimensionedField<scalar, volMesh>& dsf,
2212     const tmp<fvMatrix<Type> >& tA
2215     tmp<fvMatrix<Type> > tC(tA.ptr());
2216     tC() *= dsf;
2217     return tC;
2220 template<class Type>
2221 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator*
2223     const tmp<DimensionedField<scalar, volMesh> >& tdsf,
2224     const tmp<fvMatrix<Type> >& tA
2227     tmp<fvMatrix<Type> > tC(tA.ptr());
2228     tC() *= tdsf;
2229     return tC;
2232 template<class Type>
2233 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator*
2235     const tmp<volScalarField>& tvsf,
2236     const tmp<fvMatrix<Type> >& tA
2239     tmp<fvMatrix<Type> > tC(tA.ptr());
2240     tC() *= tvsf;
2241     return tC;
2244 template<class Type>
2245 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator*
2247     const dimensioned<scalar>& ds,
2248     const fvMatrix<Type>& A
2251     tmp<fvMatrix<Type> > tC(new fvMatrix<Type>(A));
2252     tC() *= ds;
2253     return tC;
2256 template<class Type>
2257 Foam::tmp<Foam::fvMatrix<Type> > Foam::operator*
2259     const dimensioned<scalar>& ds,
2260     const tmp<fvMatrix<Type> >& tA
2263     tmp<fvMatrix<Type> > tC(tA.ptr());
2264     tC() *= ds;
2265     return tC;
2269 template<class Type>
2270 Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
2271 Foam::operator&
2273     const fvMatrix<Type>& M,
2274     const DimensionedField<Type, volMesh>& psi
2277     tmp<GeometricField<Type, fvPatchField, volMesh> > tMphi
2278     (
2279         new GeometricField<Type, fvPatchField, volMesh>
2280         (
2281             IOobject
2282             (
2283                 "M&" + psi.name(),
2284                 psi.instance(),
2285                 psi.mesh(),
2286                 IOobject::NO_READ,
2287                 IOobject::NO_WRITE
2288             ),
2289             psi.mesh(),
2290             M.dimensions()/dimVol,
2291             zeroGradientFvPatchScalarField::typeName
2292         )
2293     );
2294     GeometricField<Type, fvPatchField, volMesh>& Mphi = tMphi();
2296     // Loop over field components
2297     for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
2298     {
2299         scalarField psiCmpt(psi.field().component(cmpt));
2300         scalarField boundaryDiagCmpt(M.diag());
2301         M.addBoundaryDiag(boundaryDiagCmpt, cmpt);
2302         Mphi.internalField().replace(cmpt, -boundaryDiagCmpt*psiCmpt);
2303     }
2305     Mphi.internalField() += M.lduMatrix::H(psi.field()) + M.source();
2306     M.addBoundarySource(Mphi.internalField());
2308     Mphi.internalField() /= -psi.mesh().V();
2309     Mphi.correctBoundaryConditions();
2311     return tMphi;
2314 template<class Type>
2315 Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
2316 Foam::operator&
2318     const fvMatrix<Type>& M,
2319     const tmp<DimensionedField<Type, volMesh> >& tpsi
2322     tmp<GeometricField<Type, fvPatchField, volMesh> > tMpsi = M & tpsi();
2323     tpsi.clear();
2324     return tMpsi;
2327 template<class Type>
2328 Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
2329 Foam::operator&
2331     const fvMatrix<Type>& M,
2332     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tpsi
2335     tmp<GeometricField<Type, fvPatchField, volMesh> > tMpsi = M & tpsi();
2336     tpsi.clear();
2337     return tMpsi;
2340 template<class Type>
2341 Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
2342 Foam::operator&
2344     const tmp<fvMatrix<Type> >& tM,
2345     const DimensionedField<Type, volMesh>& psi
2348     tmp<GeometricField<Type, fvPatchField, volMesh> > tMpsi = tM() & psi;
2349     tM.clear();
2350     return tMpsi;
2353 template<class Type>
2354 Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
2355 Foam::operator&
2357     const tmp<fvMatrix<Type> >& tM,
2358     const tmp<DimensionedField<Type, volMesh> >& tpsi
2361     tmp<GeometricField<Type, fvPatchField, volMesh> > tMpsi = tM() & tpsi();
2362     tM.clear();
2363     tpsi.clear();
2364     return tMpsi;
2367 template<class Type>
2368 Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
2369 Foam::operator&
2371     const tmp<fvMatrix<Type> >& tM,
2372     const tmp<GeometricField<Type, fvPatchField, volMesh> >& tpsi
2375     tmp<GeometricField<Type, fvPatchField, volMesh> > tMpsi = tM() & tpsi();
2376     tM.clear();
2377     tpsi.clear();
2378     return tMpsi;
2382 // * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
2384 template<class Type>
2385 Foam::Ostream& Foam::operator<<(Ostream& os, const fvMatrix<Type>& fvm)
2387     os  << static_cast<const lduMatrix&>(fvm) << nl
2388         << fvm.dimensions_ << nl
2389         << fvm.source_ << nl
2390         << fvm.internalCoeffs_ << nl
2391         << fvm.boundaryCoeffs_ << endl;
2393     os.check("Ostream& operator<<(Ostream&, fvMatrix<Type>&");
2395     return os;
2399 // * * * * * * * * * * * * * * * * Solvers * * * * * * * * * * * * * * * * * //
2401 #include "fvMatrixSolve.C"
2403 // ************************************************************************* //