fvMatrix.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "volFields.H"
27 #include "surfaceFields.H"
30 #include "coupledFvPatchFields.H"
31 #include "UIndirectList.H"
32 #include "UCompactListList.H"
33 #include "fvmDdt.H"
34 
35 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
36 
37 template<class Type>
38 template<class Type2>
40 (
41  const labelUList& addr,
42  const Field<Type2>& pf,
43  Field<Type2>& intf
44 ) const
45 {
46  if (addr.size() != pf.size())
47  {
49  << "sizes of addressing and field are different"
50  << abort(FatalError);
51  }
52 
53  forAll(addr, facei)
54  {
55  intf[addr[facei]] += pf[facei];
56  }
57 }
58 
59 
60 template<class Type>
61 template<class Type2>
63 (
64  const labelUList& addr,
65  const tmp<Field<Type2>>& tpf,
66  Field<Type2>& intf
67 ) const
68 {
69  addToInternalField(addr, tpf(), intf);
70  tpf.clear();
71 }
72 
73 
74 template<class Type>
75 template<class Type2>
77 (
78  const labelUList& addr,
79  const Field<Type2>& pf,
80  Field<Type2>& intf
81 ) const
82 {
83  if (addr.size() != pf.size())
84  {
86  << "sizes of addressing and field are different"
87  << abort(FatalError);
88  }
89 
90  forAll(addr, facei)
91  {
92  intf[addr[facei]] -= pf[facei];
93  }
94 }
95 
96 
97 template<class Type>
98 template<class Type2>
100 (
101  const labelUList& addr,
102  const tmp<Field<Type2>>& tpf,
103  Field<Type2>& intf
104 ) const
105 {
106  subtractFromInternalField(addr, tpf(), intf);
107  tpf.clear();
108 }
109 
110 
111 template<class Type>
113 (
114  scalarField& diag,
115  const direction solveCmpt
116 ) const
117 {
118  forAll(internalCoeffs_, patchi)
119  {
120  addToInternalField
121  (
122  lduAddr().patchAddr(patchi),
123  internalCoeffs_[patchi].component(solveCmpt),
124  diag
125  );
126  }
127 }
128 
129 
130 template<class Type>
132 {
133  forAll(internalCoeffs_, patchi)
134  {
135  addToInternalField
136  (
137  lduAddr().patchAddr(patchi),
138  cmptAv(internalCoeffs_[patchi]),
139  diag
140  );
141  }
142 }
143 
144 
145 template<class Type>
147 (
148  Field<Type>& source,
149  const bool couples
150 ) const
151 {
152  forAll(psi_.boundaryField(), patchi)
153  {
154  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
155  const Field<Type>& pbc = boundaryCoeffs_[patchi];
156 
157  if (!ptf.coupled())
158  {
159  addToInternalField(lduAddr().patchAddr(patchi), pbc, source);
160  }
161  else if (couples)
162  {
163  const tmp<Field<Type>> tpnf = ptf.patchNeighbourField();
164  const Field<Type>& pnf = tpnf();
165 
166  const labelUList& addr = lduAddr().patchAddr(patchi);
167 
168  forAll(addr, facei)
169  {
170  source[addr[facei]] += cmptMultiply(pbc[facei], pnf[facei]);
171  }
172  }
173  }
174 }
175 
176 
177 template<class Type>
179 (
180  const label celli,
181  const Type& value
182 )
183 {
184  const fvMesh& mesh = psi_.mesh();
185 
186  const cellList& cells = mesh.cells();
187  const labelUList& own = mesh.owner();
188  const labelUList& nei = mesh.neighbour();
189 
190  scalarField& Diag = diag();
191 
192  Field<Type>& psi =
193  const_cast<VolField<Type>&>(psi_)
195 
196  psi[celli] = value;
197  source_[celli] = value*Diag[celli];
198 
199  if (symmetric() || asymmetric())
200  {
201  const cell& c = cells[celli];
202 
203  forAll(c, j)
204  {
205  const label facei = c[j];
206 
207  if (mesh.isInternalFace(facei))
208  {
209  if (symmetric())
210  {
211  if (celli == own[facei])
212  {
213  source_[nei[facei]] -= upper()[facei]*value;
214  }
215  else
216  {
217  source_[own[facei]] -= upper()[facei]*value;
218  }
219 
220  upper()[facei] = 0.0;
221  }
222  else
223  {
224  if (celli == own[facei])
225  {
226  source_[nei[facei]] -= lower()[facei]*value;
227  }
228  else
229  {
230  source_[own[facei]] -= upper()[facei]*value;
231  }
232 
233  upper()[facei] = 0.0;
234  lower()[facei] = 0.0;
235  }
236  }
237  else
238  {
239  const label bFacei = facei - mesh.nInternalFaces();
240 
241  const labelUList patches =
242  mesh.polyBFacePatches()[bFacei];
243  const labelUList patchFaces =
244  mesh.polyBFacePatchFaces()[bFacei];
245 
246  forAll(patches, i)
247  {
248  internalCoeffs_[patches[i]][patchFaces[i]] = Zero;
249  boundaryCoeffs_[patches[i]][patchFaces[i]] = Zero;
250  }
251  }
252  }
253  }
254 }
255 
256 
257 template<class Type>
259 (
260  const label celli,
261  const Type& value,
262  const scalar fraction,
263  const scalarField& ddtDiag
264 )
265 {
266  Field<Type>& psi =
267  const_cast<VolField<Type>&>(psi_)
269 
270  psi[celli] = (1 - fraction)*psi[celli] + fraction*value;
271 
272  const scalar coeff =
273  fraction/(1 - fraction)
274  *(diag()[celli] - ddtDiag[celli]);
275 
276  diag()[celli] += coeff;
277  source()[celli] += coeff*value;
278 }
279 
280 
281 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
282 
283 template<class Type>
285 (
286  const VolField<Type>& psi,
287  const dimensionSet& ds
288 )
289 :
290  lduMatrix(psi.mesh()),
291  psi_(psi),
292  dimensions_(ds),
293  source_(psi.size(), Zero),
294  internalCoeffs_(psi.mesh().boundary().size()),
295  boundaryCoeffs_(psi.mesh().boundary().size()),
296  faceFluxCorrectionPtr_(nullptr)
297 {
298  if (debug)
299  {
301  << "Constructing fvMatrix<Type> for field " << psi_.name() << endl;
302  }
303 
304  // Initialise coupling coefficients
305  forAll(psi.mesh().boundary(), patchi)
306  {
307  internalCoeffs_.set
308  (
309  patchi,
310  new Field<Type>
311  (
312  psi.mesh().boundary()[patchi].size(),
313  Zero
314  )
315  );
316 
317  boundaryCoeffs_.set
318  (
319  patchi,
320  new Field<Type>
321  (
322  psi.mesh().boundary()[patchi].size(),
323  Zero
324  )
325  );
326  }
327 
328  // Update the boundary coefficients of psi without changing its event No.
329  VolField<Type>& psiRef = const_cast<VolField<Type>&>(psi_);
330 
331  const uint64_t currentStatePsi = psiRef.eventNo();
332  psiRef.boundaryFieldRef().updateCoeffs();
333  psiRef.eventNo() = currentStatePsi;
334 }
335 
336 
337 template<class Type>
339 :
340  tmp<fvMatrix<Type>>::refCount(),
341  lduMatrix(fvm),
342  psi_(fvm.psi_),
343  dimensions_(fvm.dimensions_),
344  source_(fvm.source_),
345  internalCoeffs_(fvm.internalCoeffs_),
346  boundaryCoeffs_(fvm.boundaryCoeffs_),
347  faceFluxCorrectionPtr_(nullptr)
348 {
349  if (debug)
350  {
352  << "Copying fvMatrix<Type> for field " << psi_.name() << endl;
353  }
354 
355  if (fvm.faceFluxCorrectionPtr_)
356  {
357  faceFluxCorrectionPtr_ = new
359  (
360  *(fvm.faceFluxCorrectionPtr_)
361  );
362  }
363 }
364 
365 
366 template<class Type>
368 :
369  lduMatrix
370  (
371  const_cast<fvMatrix<Type>&>(tfvm()),
372  tfvm.isTmp()
373  ),
374  psi_(tfvm().psi_),
375  dimensions_(tfvm().dimensions_),
376  source_
377  (
378  const_cast<fvMatrix<Type>&>(tfvm()).source_,
379  tfvm.isTmp()
380  ),
381  internalCoeffs_
382  (
383  const_cast<fvMatrix<Type>&>(tfvm()).internalCoeffs_,
384  tfvm.isTmp()
385  ),
386  boundaryCoeffs_
387  (
388  const_cast<fvMatrix<Type>&>(tfvm()).boundaryCoeffs_,
389  tfvm.isTmp()
390  ),
391  faceFluxCorrectionPtr_(nullptr)
392 {
393  if (debug)
394  {
396  << "Copying fvMatrix<Type> for field " << psi_.name() << endl;
397  }
398 
399  if (tfvm().faceFluxCorrectionPtr_)
400  {
401  if (tfvm.isTmp())
402  {
403  faceFluxCorrectionPtr_ = tfvm().faceFluxCorrectionPtr_;
404  tfvm().faceFluxCorrectionPtr_ = nullptr;
405  }
406  else
407  {
408  faceFluxCorrectionPtr_ = new
410  (
411  *(tfvm().faceFluxCorrectionPtr_)
412  );
413  }
414  }
415 
416  tfvm.clear();
417 }
418 
419 
420 template<class Type>
422 (
423  const VolField<Type>& psi,
424  Istream& is
425 )
426 :
427  lduMatrix(psi.mesh()),
428  psi_(psi),
429  dimensions_(is),
430  source_(is),
431  internalCoeffs_(psi.mesh().boundary().size()),
432  boundaryCoeffs_(psi.mesh().boundary().size()),
433  faceFluxCorrectionPtr_(nullptr)
434 {
435  if (debug)
436  {
438  << "Constructing fvMatrix<Type> for field " << psi_.name() << endl;
439  }
440 
441  // Initialise coupling coefficients
442  forAll(psi.mesh().boundary(), patchi)
443  {
444  internalCoeffs_.set
445  (
446  patchi,
447  new Field<Type>
448  (
449  psi.mesh().boundary()[patchi].size(),
450  Zero
451  )
452  );
453 
454  boundaryCoeffs_.set
455  (
456  patchi,
457  new Field<Type>
458  (
459  psi.mesh().boundary()[patchi].size(),
460  Zero
461  )
462  );
463  }
464 
465 }
466 
467 
468 template<class Type>
470 {
471  return tmp<fvMatrix<Type>>
472  (
473  new fvMatrix<Type>(*this)
474  );
475 }
476 
477 
478 // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * * //
479 
480 template<class Type>
482 {
483  if (debug)
484  {
486  << "Destroying fvMatrix<Type> for field " << psi_.name() << endl;
487  }
488 
489  if (faceFluxCorrectionPtr_)
490  {
491  delete faceFluxCorrectionPtr_;
492  }
493 }
494 
495 
496 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
497 
498 template<class Type>
499 template<template<class> class ListType>
501 (
502  const labelUList& cellLabels,
503  const ListType<Type>& values
504 )
505 {
506  // Fix the values
507  forAll(cellLabels, i)
508  {
509  setValue(cellLabels[i], values[i]);
510  }
511 }
512 
513 
514 template<class Type>
515 template<template<class> class ListType>
517 (
518  const labelUList& cellLabels,
519  const ListType<Type>& values,
520  const scalarList& fractions,
521  const bool hasDdt
522 )
523 {
524  // Get the proportion of the diagonal associated with iterative update
525  scalarField ddtDiag(diag().size(), 0);
526  const scalar alpha = relaxationFactor();
527  if (alpha > 0)
528  {
529  ddtDiag += (1 - alpha)*diag();
530  }
531  if (hasDdt)
532  {
533  const fvMatrix<Type> ddtEqn(fvm::ddt(psi_));
534  if (ddtEqn.hasDiag())
535  {
536  ddtDiag += ddtEqn.diag();
537  }
538  }
539 
540  forAll(cellLabels, i)
541  {
542  if (- rootSmall < fractions[i] && fractions[i] < rootSmall)
543  {
544  // Do nothing
545  }
546  else if (1 - rootSmall < fractions[i] && fractions[i] < 1 + rootSmall)
547  {
548  // Fix the values
549  setValue(cellLabels[i], values[i]);
550  }
551  else
552  {
553  // Fractionally fix the values
554  setValue(cellLabels[i], values[i], fractions[i], ddtDiag);
555  }
556  }
557 }
558 
559 
560 template<class Type>
562 (
563  const label celli,
564  const Type& value,
565  const bool forceReference
566 )
567 {
568  if ((forceReference || psi_.needReference()) && celli >= 0)
569  {
570  source()[celli] += diag()[celli]*value;
571  diag()[celli] += diag()[celli];
572  }
573 }
574 
575 
576 template<class Type>
578 {
579  if
580  (
582  && psi_.mesh().solution().relaxEquation(psi_.name() + "Final")
583  )
584  {
585  return psi_.mesh().solution().equationRelaxationFactor
586  (
587  psi_.name() + "Final"
588  );
589  }
590  else if (psi_.mesh().solution().relaxEquation(psi_.name()))
591  {
592  return psi_.mesh().solution().equationRelaxationFactor(psi_.name());
593  }
594  else
595  {
596  return 0;
597  }
598 }
599 
600 
601 template<class Type>
603 {
604  if (alpha <= 0)
605  {
606  return;
607  }
608 
609  if (debug)
610  {
612  << "Relaxing " << psi_.name() << " by " << alpha << endl;
613  }
614 
615  Field<Type>& S = source();
616  scalarField& D = diag();
617 
618  // Store the current unrelaxed diagonal for use in updating the source
619  scalarField D0(D);
620 
621  // Calculate the sum-mag off-diagonal from the interior faces
622  scalarField sumOff(D.size(), 0.0);
623  sumMagOffDiag(sumOff);
624 
625  // Handle the boundary contributions to the diagonal
626  forAll(psi_.boundaryField(), patchi)
627  {
628  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
629 
630  if (ptf.size())
631  {
632  const labelUList& pa = lduAddr().patchAddr(patchi);
633  Field<Type>& iCoeffs = internalCoeffs_[patchi];
634 
635  if (ptf.coupled())
636  {
637  const Field<Type>& pCoeffs = boundaryCoeffs_[patchi];
638 
639  // For coupled boundaries add the diagonal and
640  // off-diagonal contributions
641  forAll(pa, face)
642  {
643  D[pa[face]] += component(iCoeffs[face], 0);
644  sumOff[pa[face]] += mag(component(pCoeffs[face], 0));
645  }
646  }
647  else
648  {
649  // For non-coupled boundaries add the maximum magnitude diagonal
650  // contribution to ensure stability
651  forAll(pa, face)
652  {
653  D[pa[face]] += cmptMax(cmptMag(iCoeffs[face]));
654  }
655  }
656  }
657  }
658 
659 
660  if (debug)
661  {
662  // Calculate amount of non-dominance.
663  label nNon = 0;
664  scalar maxNon = 0.0;
665  scalar sumNon = 0.0;
666  forAll(D, celli)
667  {
668  scalar d = (sumOff[celli] - D[celli])/mag(D[celli]);
669 
670  if (d > 0)
671  {
672  nNon++;
673  maxNon = max(maxNon, d);
674  sumNon += d;
675  }
676  }
677 
678  reduce(nNon, sumOp<label>(), UPstream::msgType(), psi_.mesh().comm());
679  reduce
680  (
681  maxNon,
682  maxOp<scalar>(),
684  psi_.mesh().comm()
685  );
686  reduce
687  (
688  sumNon,
689  sumOp<scalar>(),
691  psi_.mesh().comm()
692  );
693  sumNon /= returnReduce
694  (
695  D.size(),
696  sumOp<label>(),
698  psi_.mesh().comm()
699  );
700 
702  << "Matrix dominance test for " << psi_.name() << nl
703  << " number of non-dominant cells : " << nNon << nl
704  << " maximum relative non-dominance : " << maxNon << nl
705  << " average relative non-dominance : " << sumNon << nl
706  << endl;
707  }
708 
709 
710  // Ensure the matrix is diagonally dominant...
711  // Assumes that the central coefficient is positive and ensures it is
712  forAll(D, celli)
713  {
714  D[celli] = max(mag(D[celli]), sumOff[celli]);
715  }
716 
717  // ... then relax
718  D /= alpha;
719 
720  // Now remove the diagonal contribution from coupled boundaries
721  forAll(psi_.boundaryField(), patchi)
722  {
723  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
724 
725  if (ptf.size())
726  {
727  const labelUList& pa = lduAddr().patchAddr(patchi);
728  Field<Type>& iCoeffs = internalCoeffs_[patchi];
729 
730  if (ptf.coupled())
731  {
732  forAll(pa, face)
733  {
734  D[pa[face]] -= component(iCoeffs[face], 0);
735  }
736  }
737  else
738  {
739  forAll(pa, face)
740  {
741  D[pa[face]] -= cmptMin(iCoeffs[face]);
742  }
743  }
744  }
745  }
746 
747  // Finally add the relaxation contribution to the source.
748  S += (D - D0)*psi_.primitiveField();
749 }
750 
751 
752 template<class Type>
754 {
755  relax(relaxationFactor());
756 }
757 
758 
759 template<class Type>
761 (
762  typename VolField<Type>::
763  Boundary& bFields
764 )
765 {
766  forAll(bFields, patchi)
767  {
768  bFields[patchi].manipulateMatrix(*this);
769  }
770 }
771 
772 
773 template<class Type>
775 {
776  tmp<scalarField> tdiag(new scalarField(diag()));
777  addCmptAvBoundaryDiag(tdiag.ref());
778  return tdiag;
779 }
780 
781 
782 template<class Type>
784 {
786 
787  forAll(psi_.boundaryField(), patchi)
788  {
789  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
790 
791  if (!ptf.coupled() && ptf.size())
792  {
793  addToInternalField
794  (
795  lduAddr().patchAddr(patchi),
796  internalCoeffs_[patchi],
797  tdiag.ref()
798  );
799  }
800  }
801 
802  return tdiag;
803 }
804 
805 
806 template<class Type>
808 {
809  tmp<volScalarField> tAphi
810  (
812  (
813  "A(" + psi_.name() + ')',
814  psi_.mesh(),
815  dimensions_/psi_.dimensions()/dimVolume,
817  )
818  );
819 
820  tAphi.ref().primitiveFieldRef() = D()/psi_.mesh().V();
821  tAphi.ref().correctBoundaryConditions();
822 
823  return tAphi;
824 }
825 
826 
827 template<class Type>
829 {
831  (
833  (
834  "Su(" +psi_.name() + ')',
835  psi_.mesh(),
836  dimensions_/dimVolume,
837  -source()/psi_.mesh().V()
838  )
839  );
840 
841  return tSu;
842 }
843 
844 
845 template<class Type>
847 {
849  (
851  (
852  "Sp(" + psi_.name() + ')',
853  psi_.mesh(),
854  dimensions_/psi_.dimensions()/dimVolume,
855  hasDiag()
856  ? diag()/psi_.mesh().V()
857  : tmp<scalarField>(new scalarField(lduAddr().size(), scalar(0)))
858  )
859  );
860 
861  return tSp;
862 }
863 
864 
865 template<class Type>
868 {
869  tmp<VolField<Type>> tHphi
870  (
872  (
873  "H(" + psi_.name() + ')',
874  psi_.mesh(),
875  dimensions_/dimVolume,
877  )
878  );
879  VolField<Type>& Hphi = tHphi.ref();
880 
881  // Loop over field components
882  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
883  {
884  scalarField psiCmpt(psi_.primitiveField().component(cmpt));
885 
886  scalarField boundaryDiagCmpt(psi_.size(), 0.0);
887  addBoundaryDiag(boundaryDiagCmpt, cmpt);
888  boundaryDiagCmpt.negate();
889  addCmptAvBoundaryDiag(boundaryDiagCmpt);
890 
891  Hphi.primitiveFieldRef().replace(cmpt, boundaryDiagCmpt*psiCmpt);
892  }
893 
894  Hphi.primitiveFieldRef() += lduMatrix::H(psi_.primitiveField()) + source_;
895  addBoundarySource(Hphi.primitiveFieldRef());
896 
897  Hphi.primitiveFieldRef() /= psi_.mesh().V();
899 
900  typename Type::labelType validComponents
901  (
902  psi_.mesh().template validComponents<Type>()
903  );
904 
905  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
906  {
907  if (validComponents[cmpt] == -1)
908  {
909  Hphi.replace
910  (
911  cmpt,
912  dimensionedScalar(Hphi.dimensions(), 0)
913  );
914  }
915  }
916 
917  return tHphi;
918 }
919 
920 
921 template<class Type>
923 {
925  (
927  (
928  "H(1)",
929  psi_.mesh(),
930  dimensions_/(dimVolume*psi_.dimensions()),
932  )
933  );
934  volScalarField& H1_ = tH1.ref();
935 
937 
938  forAll(psi_.boundaryField(), patchi)
939  {
940  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
941 
942  if (ptf.coupled() && ptf.size())
943  {
944  addToInternalField
945  (
946  lduAddr().patchAddr(patchi),
947  boundaryCoeffs_[patchi].component(0),
948  H1_
949  );
950  }
951  }
952 
953  H1_.primitiveFieldRef() /= psi_.mesh().V();
955 
956  return tH1;
957 }
958 
959 
960 template<class Type>
963 flux() const
964 {
965  if (!psi_.mesh().schemes().fluxRequired(psi_.name()))
966  {
968  << "flux requested but " << psi_.name()
969  << " not specified in the fluxRequired sub-dictionary"
970  " of fvSchemes."
971  << abort(FatalError);
972  }
973 
974  // construct SurfaceField<Type>
975  tmp<SurfaceField<Type>> tfieldFlux
976  (
978  (
979  "flux(" + psi_.name() + ')',
980  psi_.mesh(),
981  dimensions()
982  )
983  );
984  SurfaceField<Type>& fieldFlux =
985  tfieldFlux.ref();
986 
987  for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
988  {
989  fieldFlux.primitiveFieldRef().replace
990  (
991  cmpt,
992  lduMatrix::faceH(psi_.primitiveField().component(cmpt))
993  );
994  }
995 
996  FieldField<Field, Type> InternalContrib = internalCoeffs_;
997 
998  forAll(InternalContrib, patchi)
999  {
1000  InternalContrib[patchi] =
1001  cmptMultiply
1002  (
1003  InternalContrib[patchi],
1004  psi_.boundaryField()[patchi].patchInternalField()
1005  );
1006  }
1007 
1008  FieldField<Field, Type> NeighbourContrib = boundaryCoeffs_;
1009 
1010  forAll(NeighbourContrib, patchi)
1011  {
1012  if (psi_.boundaryField()[patchi].coupled())
1013  {
1014  NeighbourContrib[patchi] =
1015  cmptMultiply
1016  (
1017  NeighbourContrib[patchi],
1018  psi_.boundaryField()[patchi].patchNeighbourField()
1019  );
1020  }
1021  }
1022 
1023  typename SurfaceField<Type>::
1024  Boundary& ffbf = fieldFlux.boundaryFieldRef();
1025 
1026  forAll(ffbf, patchi)
1027  {
1028  ffbf[patchi] = InternalContrib[patchi] - NeighbourContrib[patchi];
1029  }
1030 
1031  if (faceFluxCorrectionPtr_)
1032  {
1033  fieldFlux += *faceFluxCorrectionPtr_;
1034  }
1035 
1036  return tfieldFlux;
1037 }
1038 
1039 
1040 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1041 
1042 template<class Type>
1044 {
1045  if (this == &fvmv)
1046  {
1048  << "attempted assignment to self"
1049  << abort(FatalError);
1050  }
1051 
1052  if (&psi_ != &(fvmv.psi_))
1053  {
1055  << "different fields"
1056  << abort(FatalError);
1057  }
1058 
1059  dimensions_ = fvmv.dimensions_;
1060  lduMatrix::operator=(fvmv);
1061  source_ = fvmv.source_;
1062  internalCoeffs_ = fvmv.internalCoeffs_;
1063  boundaryCoeffs_ = fvmv.boundaryCoeffs_;
1064 
1065  if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
1066  {
1067  *faceFluxCorrectionPtr_ = *fvmv.faceFluxCorrectionPtr_;
1068  }
1069  else if (fvmv.faceFluxCorrectionPtr_)
1070  {
1071  faceFluxCorrectionPtr_ =
1072  new SurfaceField<Type>
1073  (*fvmv.faceFluxCorrectionPtr_);
1074  }
1075 }
1076 
1077 
1078 template<class Type>
1080 {
1081  operator=(tfvmv());
1082  tfvmv.clear();
1083 }
1084 
1085 
1086 template<class Type>
1088 {
1090  source_.negate();
1091  internalCoeffs_.negate();
1092  boundaryCoeffs_.negate();
1093 
1094  if (faceFluxCorrectionPtr_)
1095  {
1096  faceFluxCorrectionPtr_->negate();
1097  }
1098 }
1099 
1100 
1101 template<class Type>
1103 {
1104  checkMethod(*this, fvmv, "+=");
1105 
1106  dimensions_ += fvmv.dimensions_;
1107  lduMatrix::operator+=(fvmv);
1108  source_ += fvmv.source_;
1109  internalCoeffs_ += fvmv.internalCoeffs_;
1110  boundaryCoeffs_ += fvmv.boundaryCoeffs_;
1111 
1112  if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
1113  {
1114  *faceFluxCorrectionPtr_ += *fvmv.faceFluxCorrectionPtr_;
1115  }
1116  else if (fvmv.faceFluxCorrectionPtr_)
1117  {
1118  faceFluxCorrectionPtr_ = new
1120  (
1121  *fvmv.faceFluxCorrectionPtr_
1122  );
1123  }
1124 }
1125 
1126 
1127 template<class Type>
1129 {
1130  operator+=(tfvmv());
1131  tfvmv.clear();
1132 }
1133 
1134 
1135 template<class Type>
1137 {
1138  checkMethod(*this, fvmv, "-=");
1139 
1140  dimensions_ -= fvmv.dimensions_;
1141  lduMatrix::operator-=(fvmv);
1142  source_ -= fvmv.source_;
1143  internalCoeffs_ -= fvmv.internalCoeffs_;
1144  boundaryCoeffs_ -= fvmv.boundaryCoeffs_;
1145 
1146  if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
1147  {
1148  *faceFluxCorrectionPtr_ -= *fvmv.faceFluxCorrectionPtr_;
1149  }
1150  else if (fvmv.faceFluxCorrectionPtr_)
1151  {
1152  faceFluxCorrectionPtr_ =
1153  new SurfaceField<Type>
1154  (-*fvmv.faceFluxCorrectionPtr_);
1155  }
1156 }
1157 
1158 
1159 template<class Type>
1161 {
1162  operator-=(tfvmv());
1163  tfvmv.clear();
1164 }
1165 
1166 
1167 template<class Type>
1169 (
1171 )
1172 {
1173  checkMethod(*this, su, "+=");
1174  source() -= su.mesh().V()*su.primitiveField();
1175 }
1176 
1177 
1178 template<class Type>
1180 (
1182 )
1183 {
1184  operator+=(tsu());
1185  tsu.clear();
1186 }
1187 
1188 
1189 template<class Type>
1191 (
1192  const tmp<VolField<Type>>& tsu
1193 )
1194 {
1195  operator+=(tsu());
1196  tsu.clear();
1197 }
1198 
1199 
1200 template<class Type>
1202 (
1204 )
1205 {
1206  checkMethod(*this, su, "-=");
1207  source() += su.mesh().V()*su.primitiveField();
1208 }
1209 
1210 
1211 template<class Type>
1213 (
1215 )
1216 {
1217  operator-=(tsu());
1218  tsu.clear();
1219 }
1220 
1221 
1222 template<class Type>
1224 (
1225  const tmp<VolField<Type>>& tsu
1226 )
1227 {
1228  operator-=(tsu());
1229  tsu.clear();
1230 }
1231 
1232 
1233 template<class Type>
1235 (
1236  const dimensioned<Type>& su
1237 )
1238 {
1239  source() -= psi().mesh().V()*su;
1240 }
1241 
1242 
1243 template<class Type>
1245 (
1246  const dimensioned<Type>& su
1247 )
1248 {
1249  source() += psi().mesh().V()*su;
1250 }
1251 
1252 
1253 template<class Type>
1255 (
1256  const zero&
1257 )
1258 {}
1259 
1260 
1261 template<class Type>
1263 (
1264  const zero&
1265 )
1266 {}
1267 
1268 
1269 template<class Type>
1271 (
1272  const volScalarField::Internal& dsf
1273 )
1274 {
1275  dimensions_ *= dsf.dimensions();
1276  lduMatrix::operator*=(dsf.primitiveField());
1277  source_ *= dsf.primitiveField();
1278 
1279  forAll(boundaryCoeffs_, patchi)
1280  {
1281  scalarField pisf
1282  (
1283  dsf.mesh().boundary()[patchi].patchInternalField
1284  (
1285  dsf.primitiveField()
1286  )
1287  );
1288 
1289  internalCoeffs_[patchi] *= pisf;
1290  boundaryCoeffs_[patchi] *= pisf;
1291  }
1292 
1293  if (faceFluxCorrectionPtr_)
1294  {
1296  << "cannot scale a matrix containing a faceFluxCorrection"
1297  << abort(FatalError);
1298  }
1299 }
1300 
1301 
1302 template<class Type>
1304 (
1305  const tmp<volScalarField::Internal>& tdsf
1306 )
1307 {
1308  operator*=(tdsf());
1309  tdsf.clear();
1310 }
1311 
1312 
1313 template<class Type>
1315 (
1316  const tmp<volScalarField>& tvsf
1317 )
1318 {
1319  operator*=(tvsf());
1320  tvsf.clear();
1321 }
1322 
1323 
1324 template<class Type>
1326 (
1327  const dimensioned<scalar>& ds
1328 )
1329 {
1330  dimensions_ *= ds.dimensions();
1331  lduMatrix::operator*=(ds.value());
1332  source_ *= ds.value();
1333  internalCoeffs_ *= ds.value();
1334  boundaryCoeffs_ *= ds.value();
1335 
1336  if (faceFluxCorrectionPtr_)
1337  {
1338  *faceFluxCorrectionPtr_ *= ds.value();
1339  }
1340 }
1341 
1342 
1343 template<class Type>
1345 (
1346  const volScalarField::Internal& dsf
1347 )
1348 {
1349  dimensions_ /= dsf.dimensions();
1350  lduMatrix::operator/=(dsf.primitiveField());
1351  source_ /= dsf.primitiveField();
1352 
1353  forAll(boundaryCoeffs_, patchi)
1354  {
1355  scalarField pisf
1356  (
1357  dsf.mesh().boundary()[patchi].patchInternalField
1358  (
1359  dsf.primitiveField()
1360  )
1361  );
1362 
1363  internalCoeffs_[patchi] /= pisf;
1364  boundaryCoeffs_[patchi] /= pisf;
1365  }
1366 
1367  if (faceFluxCorrectionPtr_)
1368  {
1370  << "cannot scale a matrix containing a faceFluxCorrection"
1371  << abort(FatalError);
1372  }
1373 }
1374 
1375 
1376 template<class Type>
1378 (
1379  const tmp<volScalarField::Internal>& tdsf
1380 )
1381 {
1382  operator/=(tdsf());
1383  tdsf.clear();
1384 }
1385 
1386 
1387 template<class Type>
1389 (
1390  const tmp<volScalarField>& tvsf
1391 )
1392 {
1393  operator/=(tvsf());
1394  tvsf.clear();
1395 }
1396 
1397 
1398 template<class Type>
1400 (
1401  const dimensioned<scalar>& ds
1402 )
1403 {
1404  dimensions_ /= ds.dimensions();
1405  lduMatrix::operator/=(ds.value());
1406  source_ /= ds.value();
1407  internalCoeffs_ /= ds.value();
1408  boundaryCoeffs_ /= ds.value();
1409 
1410  if (faceFluxCorrectionPtr_)
1411  {
1412  *faceFluxCorrectionPtr_ /= ds.value();
1413  }
1414 }
1415 
1416 
1417 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
1418 
1419 template<class Type>
1421 (
1422  const fvMatrix<Type>& fvm1,
1423  const fvMatrix<Type>& fvm2,
1424  const char* op
1425 )
1426 {
1427  if (&fvm1.psi() != &fvm2.psi())
1428  {
1430  << "incompatible fields for operation "
1431  << endl << " "
1432  << "[" << fvm1.psi().name() << "] "
1433  << op
1434  << " [" << fvm2.psi().name() << "]"
1435  << abort(FatalError);
1436  }
1437 
1438  if (dimensionSet::debug && fvm1.dimensions() != fvm2.dimensions())
1439  {
1441  << "incompatible dimensions for operation "
1442  << endl << " "
1443  << "[" << fvm1.psi().name() << fvm1.dimensions()/dimVolume << " ] "
1444  << op
1445  << " [" << fvm2.psi().name() << fvm2.dimensions()/dimVolume << " ]"
1446  << abort(FatalError);
1447  }
1448 }
1449 
1450 
1451 template<class Type>
1453 (
1454  const fvMatrix<Type>& fvm,
1456  const char* op
1457 )
1458 {
1459  if (dimensionSet::debug && fvm.dimensions()/dimVolume != df.dimensions())
1460  {
1462  << endl << " "
1463  << "[" << fvm.psi().name() << fvm.dimensions()/dimVolume << " ] "
1464  << op
1465  << " [" << df.name() << df.dimensions() << " ]"
1466  << abort(FatalError);
1467  }
1468 }
1469 
1470 
1471 template<class Type>
1473 (
1474  const fvMatrix<Type>& fvm,
1475  const dimensioned<Type>& dt,
1476  const char* op
1477 )
1478 {
1479  if (dimensionSet::debug && fvm.dimensions()/dimVolume != dt.dimensions())
1480  {
1482  << "incompatible dimensions for operation "
1483  << endl << " "
1484  << "[" << fvm.psi().name() << fvm.dimensions()/dimVolume << " ] "
1485  << op
1486  << " [" << dt.name() << dt.dimensions() << " ]"
1487  << abort(FatalError);
1488  }
1489 }
1490 
1491 
1492 template<class Type>
1494 (
1495  const fvMatrix<Type>& A
1496 )
1497 {
1498  tmp<Foam::fvMatrix<Type>> tAcorr = A - (A & A.psi());
1499 
1500  // Delete the faceFluxCorrection from the correction matrix
1501  // as it does not have a clear meaning or purpose
1502  deleteDemandDrivenData(tAcorr.ref().faceFluxCorrectionPtr());
1503 
1504  return tAcorr;
1505 }
1506 
1507 
1508 template<class Type>
1510 (
1511  const tmp<fvMatrix<Type>>& tA
1512 )
1513 {
1514  tmp<Foam::fvMatrix<Type>> tAcorr = tA - (tA() & tA().psi());
1515 
1516  // Delete the faceFluxCorrection from the correction matrix
1517  // as it does not have a clear meaning or purpose
1518  deleteDemandDrivenData(tAcorr.ref().faceFluxCorrectionPtr());
1519 
1520  return tAcorr;
1521 }
1522 
1523 
1524 // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
1525 
1526 template<class Type>
1527 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1528 (
1529  const fvMatrix<Type>& A,
1530  const fvMatrix<Type>& B
1531 )
1532 {
1533  checkMethod(A, B, "==");
1534  return (A - B);
1535 }
1536 
1537 template<class Type>
1538 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1539 (
1540  const tmp<fvMatrix<Type>>& tA,
1541  const fvMatrix<Type>& B
1542 )
1543 {
1544  checkMethod(tA(), B, "==");
1545  return (tA - B);
1546 }
1547 
1548 template<class Type>
1549 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1550 (
1551  const fvMatrix<Type>& A,
1552  const tmp<fvMatrix<Type>>& tB
1553 )
1554 {
1555  checkMethod(A, tB(), "==");
1556  return (A - tB);
1557 }
1558 
1559 template<class Type>
1560 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1561 (
1562  const tmp<fvMatrix<Type>>& tA,
1563  const tmp<fvMatrix<Type>>& tB
1564 )
1565 {
1566  checkMethod(tA(), tB(), "==");
1567  return (tA - tB);
1568 }
1569 
1570 template<class Type>
1571 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1572 (
1573  const fvMatrix<Type>& A,
1574  const DimensionedField<Type, fvMesh>& su
1575 )
1576 {
1577  checkMethod(A, su, "==");
1578  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1579  tC.ref().source() += su.mesh().V()*su.primitiveField();
1580  return tC;
1581 }
1582 
1583 template<class Type>
1584 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1585 (
1586  const fvMatrix<Type>& A,
1587  const tmp<DimensionedField<Type, fvMesh>>& tsu
1588 )
1589 {
1590  checkMethod(A, tsu(), "==");
1591  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1592  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
1593  tsu.clear();
1594  return tC;
1595 }
1596 
1597 template<class Type>
1598 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1599 (
1600  const fvMatrix<Type>& A,
1601  const tmp<VolField<Type>>& tsu
1602 )
1603 {
1604  checkMethod(A, tsu(), "==");
1605  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1606  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
1607  tsu.clear();
1608  return tC;
1609 }
1610 
1611 template<class Type>
1612 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1613 (
1614  const tmp<fvMatrix<Type>>& tA,
1615  const DimensionedField<Type, fvMesh>& su
1616 )
1617 {
1618  checkMethod(tA(), su, "==");
1619  tmp<fvMatrix<Type>> tC(tA.ptr());
1620  tC.ref().source() += su.mesh().V()*su.primitiveField();
1621  return tC;
1622 }
1623 
1624 template<class Type>
1625 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1626 (
1627  const tmp<fvMatrix<Type>>& tA,
1628  const tmp<DimensionedField<Type, fvMesh>>& tsu
1629 )
1630 {
1631  checkMethod(tA(), tsu(), "==");
1632  tmp<fvMatrix<Type>> tC(tA.ptr());
1633  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
1634  tsu.clear();
1635  return tC;
1636 }
1637 
1638 template<class Type>
1639 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1640 (
1641  const tmp<fvMatrix<Type>>& tA,
1642  const tmp<VolField<Type>>& tsu
1643 )
1644 {
1645  checkMethod(tA(), tsu(), "==");
1646  tmp<fvMatrix<Type>> tC(tA.ptr());
1647  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
1648  tsu.clear();
1649  return tC;
1650 }
1651 
1652 template<class Type>
1653 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1654 (
1655  const fvMatrix<Type>& A,
1656  const dimensioned<Type>& su
1657 )
1658 {
1659  checkMethod(A, su, "==");
1660  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1661  tC.ref().source() += A.psi().mesh().V()*su.value();
1662  return tC;
1663 }
1664 
1665 template<class Type>
1666 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1667 (
1668  const tmp<fvMatrix<Type>>& tA,
1669  const dimensioned<Type>& su
1670 )
1671 {
1672  checkMethod(tA(), su, "==");
1673  tmp<fvMatrix<Type>> tC(tA.ptr());
1674  tC.ref().source() += tC().psi().mesh().V()*su.value();
1675  return tC;
1676 }
1677 
1678 template<class Type>
1679 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1680 (
1681  const fvMatrix<Type>& A,
1682  const zero&
1683 )
1684 {
1685  return A;
1686 }
1687 
1688 
1689 template<class Type>
1690 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
1691 (
1692  const tmp<fvMatrix<Type>>& tA,
1693  const zero&
1694 )
1695 {
1696  return tA;
1697 }
1698 
1699 
1700 template<class Type>
1701 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
1702 (
1703  const fvMatrix<Type>& A
1704 )
1705 {
1706  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1707  tC.ref().negate();
1708  return tC;
1709 }
1710 
1711 template<class Type>
1712 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
1713 (
1714  const tmp<fvMatrix<Type>>& tA
1715 )
1716 {
1717  tmp<fvMatrix<Type>> tC(tA.ptr());
1718  tC.ref().negate();
1719  return tC;
1720 }
1721 
1722 
1723 template<class Type>
1724 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1725 (
1726  const fvMatrix<Type>& A,
1727  const fvMatrix<Type>& B
1728 )
1729 {
1730  checkMethod(A, B, "+");
1731  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1732  tC.ref() += B;
1733  return tC;
1734 }
1735 
1736 template<class Type>
1737 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1738 (
1739  const tmp<fvMatrix<Type>>& tA,
1740  const fvMatrix<Type>& B
1741 )
1742 {
1743  checkMethod(tA(), B, "+");
1744  tmp<fvMatrix<Type>> tC(tA.ptr());
1745  tC.ref() += B;
1746  return tC;
1747 }
1748 
1749 template<class Type>
1750 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1751 (
1752  const fvMatrix<Type>& A,
1753  const tmp<fvMatrix<Type>>& tB
1754 )
1755 {
1756  checkMethod(A, tB(), "+");
1757  tmp<fvMatrix<Type>> tC(tB.ptr());
1758  tC.ref() += A;
1759  return tC;
1760 }
1761 
1762 template<class Type>
1763 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1764 (
1765  const tmp<fvMatrix<Type>>& tA,
1766  const tmp<fvMatrix<Type>>& tB
1767 )
1768 {
1769  checkMethod(tA(), tB(), "+");
1770  tmp<fvMatrix<Type>> tC(tA.ptr());
1771  tC.ref() += tB();
1772  tB.clear();
1773  return tC;
1774 }
1775 
1776 template<class Type>
1777 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1778 (
1779  const fvMatrix<Type>& A,
1780  const DimensionedField<Type, fvMesh>& su
1781 )
1782 {
1783  checkMethod(A, su, "+");
1784  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1785  tC.ref().source() -= su.mesh().V()*su.primitiveField();
1786  return tC;
1787 }
1788 
1789 template<class Type>
1790 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1791 (
1792  const fvMatrix<Type>& A,
1793  const tmp<DimensionedField<Type, fvMesh>>& tsu
1794 )
1795 {
1796  checkMethod(A, tsu(), "+");
1797  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1798  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
1799  tsu.clear();
1800  return tC;
1801 }
1802 
1803 template<class Type>
1804 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1805 (
1806  const fvMatrix<Type>& A,
1807  const tmp<VolField<Type>>& tsu
1808 )
1809 {
1810  checkMethod(A, tsu(), "+");
1811  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1812  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
1813  tsu.clear();
1814  return tC;
1815 }
1816 
1817 template<class Type>
1818 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1819 (
1820  const tmp<fvMatrix<Type>>& tA,
1821  const DimensionedField<Type, fvMesh>& su
1822 )
1823 {
1824  checkMethod(tA(), su, "+");
1825  tmp<fvMatrix<Type>> tC(tA.ptr());
1826  tC.ref().source() -= su.mesh().V()*su.primitiveField();
1827  return tC;
1828 }
1829 
1830 template<class Type>
1831 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1832 (
1833  const tmp<fvMatrix<Type>>& tA,
1834  const tmp<DimensionedField<Type, fvMesh>>& tsu
1835 )
1836 {
1837  checkMethod(tA(), tsu(), "+");
1838  tmp<fvMatrix<Type>> tC(tA.ptr());
1839  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
1840  tsu.clear();
1841  return tC;
1842 }
1843 
1844 template<class Type>
1845 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1846 (
1847  const tmp<fvMatrix<Type>>& tA,
1848  const tmp<VolField<Type>>& tsu
1849 )
1850 {
1851  checkMethod(tA(), tsu(), "+");
1852  tmp<fvMatrix<Type>> tC(tA.ptr());
1853  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
1854  tsu.clear();
1855  return tC;
1856 }
1857 
1858 template<class Type>
1859 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1860 (
1861  const DimensionedField<Type, fvMesh>& su,
1862  const fvMatrix<Type>& A
1863 )
1864 {
1865  checkMethod(A, su, "+");
1866  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1867  tC.ref().source() -= su.mesh().V()*su.primitiveField();
1868  return tC;
1869 }
1870 
1871 template<class Type>
1872 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1873 (
1874  const tmp<DimensionedField<Type, fvMesh>>& tsu,
1875  const fvMatrix<Type>& A
1876 )
1877 {
1878  checkMethod(A, tsu(), "+");
1879  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1880  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
1881  tsu.clear();
1882  return tC;
1883 }
1884 
1885 template<class Type>
1886 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1887 (
1888  const tmp<VolField<Type>>& tsu,
1889  const fvMatrix<Type>& A
1890 )
1891 {
1892  checkMethod(A, tsu(), "+");
1893  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1894  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
1895  tsu.clear();
1896  return tC;
1897 }
1898 
1899 template<class Type>
1900 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1901 (
1902  const DimensionedField<Type, fvMesh>& su,
1903  const tmp<fvMatrix<Type>>& tA
1904 )
1905 {
1906  checkMethod(tA(), su, "+");
1907  tmp<fvMatrix<Type>> tC(tA.ptr());
1908  tC.ref().source() -= su.mesh().V()*su.primitiveField();
1909  return tC;
1910 }
1911 
1912 template<class Type>
1913 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1914 (
1915  const tmp<DimensionedField<Type, fvMesh>>& tsu,
1916  const tmp<fvMatrix<Type>>& tA
1917 )
1918 {
1919  checkMethod(tA(), tsu(), "+");
1920  tmp<fvMatrix<Type>> tC(tA.ptr());
1921  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
1922  tsu.clear();
1923  return tC;
1924 }
1925 
1926 template<class Type>
1927 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
1928 (
1929  const tmp<VolField<Type>>& tsu,
1930  const tmp<fvMatrix<Type>>& tA
1931 )
1932 {
1933  checkMethod(tA(), tsu(), "+");
1934  tmp<fvMatrix<Type>> tC(tA.ptr());
1935  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
1936  tsu.clear();
1937  return tC;
1938 }
1939 
1940 
1941 template<class Type>
1942 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
1943 (
1944  const fvMatrix<Type>& A,
1945  const fvMatrix<Type>& B
1946 )
1947 {
1948  checkMethod(A, B, "-");
1949  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
1950  tC.ref() -= B;
1951  return tC;
1952 }
1953 
1954 template<class Type>
1955 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
1956 (
1957  const tmp<fvMatrix<Type>>& tA,
1958  const fvMatrix<Type>& B
1959 )
1960 {
1961  checkMethod(tA(), B, "-");
1962  tmp<fvMatrix<Type>> tC(tA.ptr());
1963  tC.ref() -= B;
1964  return tC;
1965 }
1966 
1967 template<class Type>
1968 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
1969 (
1970  const fvMatrix<Type>& A,
1971  const tmp<fvMatrix<Type>>& tB
1972 )
1973 {
1974  checkMethod(A, tB(), "-");
1975  tmp<fvMatrix<Type>> tC(tB.ptr());
1976  tC.ref() -= A;
1977  tC.ref().negate();
1978  return tC;
1979 }
1980 
1981 template<class Type>
1982 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
1983 (
1984  const tmp<fvMatrix<Type>>& tA,
1985  const tmp<fvMatrix<Type>>& tB
1986 )
1987 {
1988  checkMethod(tA(), tB(), "-");
1989  tmp<fvMatrix<Type>> tC(tA.ptr());
1990  tC.ref() -= tB();
1991  tB.clear();
1992  return tC;
1993 }
1994 
1995 template<class Type>
1996 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
1997 (
1998  const fvMatrix<Type>& A,
1999  const DimensionedField<Type, fvMesh>& su
2000 )
2001 {
2002  checkMethod(A, su, "-");
2003  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2004  tC.ref().source() += su.mesh().V()*su.primitiveField();
2005  return tC;
2006 }
2007 
2008 template<class Type>
2009 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2010 (
2011  const fvMatrix<Type>& A,
2012  const tmp<DimensionedField<Type, fvMesh>>& tsu
2013 )
2014 {
2015  checkMethod(A, tsu(), "-");
2016  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2017  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2018  tsu.clear();
2019  return tC;
2020 }
2021 
2022 template<class Type>
2023 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2024 (
2025  const fvMatrix<Type>& A,
2026  const tmp<VolField<Type>>& tsu
2027 )
2028 {
2029  checkMethod(A, tsu(), "-");
2030  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2031  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2032  tsu.clear();
2033  return tC;
2034 }
2035 
2036 template<class Type>
2037 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2038 (
2039  const tmp<fvMatrix<Type>>& tA,
2040  const DimensionedField<Type, fvMesh>& su
2041 )
2042 {
2043  checkMethod(tA(), su, "-");
2044  tmp<fvMatrix<Type>> tC(tA.ptr());
2045  tC.ref().source() += su.mesh().V()*su.primitiveField();
2046  return tC;
2047 }
2048 
2049 template<class Type>
2050 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2051 (
2052  const tmp<fvMatrix<Type>>& tA,
2053  const tmp<DimensionedField<Type, fvMesh>>& tsu
2054 )
2055 {
2056  checkMethod(tA(), tsu(), "-");
2057  tmp<fvMatrix<Type>> tC(tA.ptr());
2058  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2059  tsu.clear();
2060  return tC;
2061 }
2062 
2063 template<class Type>
2064 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2065 (
2066  const tmp<fvMatrix<Type>>& tA,
2067  const tmp<VolField<Type>>& tsu
2068 )
2069 {
2070  checkMethod(tA(), tsu(), "-");
2071  tmp<fvMatrix<Type>> tC(tA.ptr());
2072  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2073  tsu.clear();
2074  return tC;
2075 }
2076 
2077 template<class Type>
2078 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2079 (
2080  const DimensionedField<Type, fvMesh>& su,
2081  const fvMatrix<Type>& A
2082 )
2083 {
2084  checkMethod(A, su, "-");
2085  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2086  tC.ref().negate();
2087  tC.ref().source() -= su.mesh().V()*su.primitiveField();
2088  return tC;
2089 }
2090 
2091 template<class Type>
2092 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2093 (
2094  const tmp<DimensionedField<Type, fvMesh>>& tsu,
2095  const fvMatrix<Type>& A
2096 )
2097 {
2098  checkMethod(A, tsu(), "-");
2099  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2100  tC.ref().negate();
2101  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2102  tsu.clear();
2103  return tC;
2104 }
2105 
2106 template<class Type>
2107 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2108 (
2109  const tmp<VolField<Type>>& tsu,
2110  const fvMatrix<Type>& A
2111 )
2112 {
2113  checkMethod(A, tsu(), "-");
2114  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2115  tC.ref().negate();
2116  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2117  tsu.clear();
2118  return tC;
2119 }
2120 
2121 template<class Type>
2122 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2123 (
2124  const DimensionedField<Type, fvMesh>& su,
2125  const tmp<fvMatrix<Type>>& tA
2126 )
2127 {
2128  checkMethod(tA(), su, "-");
2129  tmp<fvMatrix<Type>> tC(tA.ptr());
2130  tC.ref().negate();
2131  tC.ref().source() -= su.mesh().V()*su.primitiveField();
2132  return tC;
2133 }
2134 
2135 template<class Type>
2136 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2137 (
2138  const tmp<DimensionedField<Type, fvMesh>>& tsu,
2139  const tmp<fvMatrix<Type>>& tA
2140 )
2141 {
2142  checkMethod(tA(), tsu(), "-");
2143  tmp<fvMatrix<Type>> tC(tA.ptr());
2144  tC.ref().negate();
2145  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2146  tsu.clear();
2147  return tC;
2148 }
2149 
2150 template<class Type>
2151 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2152 (
2153  const tmp<VolField<Type>>& tsu,
2154  const tmp<fvMatrix<Type>>& tA
2155 )
2156 {
2157  checkMethod(tA(), tsu(), "-");
2158  tmp<fvMatrix<Type>> tC(tA.ptr());
2159  tC.ref().negate();
2160  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2161  tsu.clear();
2162  return tC;
2163 }
2164 
2165 template<class Type>
2166 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2167 (
2168  const fvMatrix<Type>& A,
2169  const dimensioned<Type>& su
2170 )
2171 {
2172  checkMethod(A, su, "+");
2173  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2174  tC.ref().source() -= su.value()*A.psi().mesh().V();
2175  return tC;
2176 }
2177 
2178 template<class Type>
2179 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2180 (
2181  const tmp<fvMatrix<Type>>& tA,
2182  const dimensioned<Type>& su
2183 )
2184 {
2185  checkMethod(tA(), su, "+");
2186  tmp<fvMatrix<Type>> tC(tA.ptr());
2187  tC.ref().source() -= su.value()*tC().psi().mesh().V();
2188  return tC;
2189 }
2190 
2191 template<class Type>
2192 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2193 (
2194  const dimensioned<Type>& su,
2195  const fvMatrix<Type>& A
2196 )
2197 {
2198  checkMethod(A, su, "+");
2199  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2200  tC.ref().source() -= su.value()*A.psi().mesh().V();
2201  return tC;
2202 }
2203 
2204 template<class Type>
2205 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2206 (
2207  const dimensioned<Type>& su,
2208  const tmp<fvMatrix<Type>>& tA
2209 )
2210 {
2211  checkMethod(tA(), su, "+");
2212  tmp<fvMatrix<Type>> tC(tA.ptr());
2213  tC.ref().source() -= su.value()*tC().psi().mesh().V();
2214  return tC;
2215 }
2216 
2217 template<class Type>
2218 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2219 (
2220  const fvMatrix<Type>& A,
2221  const dimensioned<Type>& su
2222 )
2223 {
2224  checkMethod(A, su, "-");
2225  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2226  tC.ref().source() += su.value()*tC().psi().mesh().V();
2227  return tC;
2228 }
2229 
2230 template<class Type>
2231 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2232 (
2233  const tmp<fvMatrix<Type>>& tA,
2234  const dimensioned<Type>& su
2235 )
2236 {
2237  checkMethod(tA(), su, "-");
2238  tmp<fvMatrix<Type>> tC(tA.ptr());
2239  tC.ref().source() += su.value()*tC().psi().mesh().V();
2240  return tC;
2241 }
2242 
2243 template<class Type>
2244 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2245 (
2246  const dimensioned<Type>& su,
2247  const fvMatrix<Type>& A
2248 )
2249 {
2250  checkMethod(A, su, "-");
2251  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2252  tC.ref().negate();
2253  tC.ref().source() -= su.value()*A.psi().mesh().V();
2254  return tC;
2255 }
2256 
2257 template<class Type>
2258 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2259 (
2260  const dimensioned<Type>& su,
2261  const tmp<fvMatrix<Type>>& tA
2262 )
2263 {
2264  checkMethod(tA(), su, "-");
2265  tmp<fvMatrix<Type>> tC(tA.ptr());
2266  tC.ref().negate();
2267  tC.ref().source() -= su.value()*tC().psi().mesh().V();
2268  return tC;
2269 }
2270 
2271 
2272 template<class Type>
2273 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2274 (
2275  const volScalarField::Internal& dsf,
2276  const fvMatrix<Type>& A
2277 )
2278 {
2279  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2280  tC.ref() *= dsf;
2281  return tC;
2282 }
2283 
2284 template<class Type>
2285 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2286 (
2287  const tmp<volScalarField::Internal>& tdsf,
2288  const fvMatrix<Type>& A
2289 )
2290 {
2291  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2292  tC.ref() *= tdsf;
2293  return tC;
2294 }
2295 
2296 template<class Type>
2297 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2298 (
2299  const tmp<volScalarField>& tvsf,
2300  const fvMatrix<Type>& A
2301 )
2302 {
2303  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2304  tC.ref() *= tvsf;
2305  return tC;
2306 }
2307 
2308 template<class Type>
2309 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2310 (
2311  const volScalarField::Internal& dsf,
2312  const tmp<fvMatrix<Type>>& tA
2313 )
2314 {
2315  tmp<fvMatrix<Type>> tC(tA.ptr());
2316  tC.ref() *= dsf;
2317  return tC;
2318 }
2319 
2320 template<class Type>
2321 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2322 (
2323  const tmp<volScalarField::Internal>& tdsf,
2324  const tmp<fvMatrix<Type>>& tA
2325 )
2326 {
2327  tmp<fvMatrix<Type>> tC(tA.ptr());
2328  tC.ref() *= tdsf;
2329  return tC;
2330 }
2331 
2332 template<class Type>
2333 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2334 (
2335  const tmp<volScalarField>& tvsf,
2336  const tmp<fvMatrix<Type>>& tA
2337 )
2338 {
2339  tmp<fvMatrix<Type>> tC(tA.ptr());
2340  tC.ref() *= tvsf;
2341  return tC;
2342 }
2343 
2344 template<class Type>
2345 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2346 (
2347  const dimensioned<scalar>& ds,
2348  const fvMatrix<Type>& A
2349 )
2350 {
2351  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2352  tC.ref() *= ds;
2353  return tC;
2354 }
2355 
2356 template<class Type>
2357 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2358 (
2359  const dimensioned<scalar>& ds,
2360  const tmp<fvMatrix<Type>>& tA
2361 )
2362 {
2363  tmp<fvMatrix<Type>> tC(tA.ptr());
2364  tC.ref() *= ds;
2365  return tC;
2366 }
2367 
2368 
2369 template<class Type>
2370 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator/
2371 (
2372  const fvMatrix<Type>& A,
2373  const volScalarField::Internal& dsf
2374 )
2375 {
2376  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2377  tC.ref() /= dsf;
2378  return tC;
2379 }
2380 
2381 template<class Type>
2382 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator/
2383 (
2384  const fvMatrix<Type>& A,
2385  const tmp<volScalarField::Internal>& tdsf
2386 )
2387 {
2388  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2389  tC.ref() /= tdsf;
2390  return tC;
2391 }
2392 
2393 template<class Type>
2394 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator/
2395 (
2396  const fvMatrix<Type>& A,
2397  const tmp<volScalarField>& tvsf
2398 )
2399 {
2400  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2401  tC.ref() /= tvsf;
2402  return tC;
2403 }
2404 
2405 template<class Type>
2406 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator/
2407 (
2408  const tmp<fvMatrix<Type>>& tA,
2409  const volScalarField::Internal& dsf
2410 )
2411 {
2412  tmp<fvMatrix<Type>> tC(tA.ptr());
2413  tC.ref() /= dsf;
2414  return tC;
2415 }
2416 
2417 template<class Type>
2418 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator/
2419 (
2420  const tmp<fvMatrix<Type>>& tA,
2421  const tmp<volScalarField::Internal>& tdsf
2422 )
2423 {
2424  tmp<fvMatrix<Type>> tC(tA.ptr());
2425  tC.ref() /= tdsf;
2426  return tC;
2427 }
2428 
2429 template<class Type>
2430 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator/
2431 (
2432  const tmp<fvMatrix<Type>>& tA,
2433  const tmp<volScalarField>& tvsf
2434 )
2435 {
2436  tmp<fvMatrix<Type>> tC(tA.ptr());
2437  tC.ref() /= tvsf;
2438  return tC;
2439 }
2440 
2441 template<class Type>
2442 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator/
2443 (
2444  const fvMatrix<Type>& A,
2445  const dimensioned<scalar>& ds
2446 )
2447 {
2448  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2449  tC.ref() /= ds;
2450  return tC;
2451 }
2452 
2453 template<class Type>
2454 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator/
2455 (
2456  const tmp<fvMatrix<Type>>& tA,
2457  const dimensioned<scalar>& ds
2458 )
2459 {
2460  tmp<fvMatrix<Type>> tC(tA.ptr());
2461  tC.ref() /= ds;
2462  return tC;
2463 }
2464 
2465 
2466 template<class Type>
2468 Foam::operator&
2469 (
2470  const fvMatrix<Type>& M,
2471  const DimensionedField<Type, fvMesh>& psi
2472 )
2473 {
2474  tmp<VolField<Type>> tMphi
2475  (
2477  (
2478  "M&" + psi.name(),
2479  psi.mesh(),
2480  M.dimensions()/dimVolume,
2482  )
2483  );
2484  VolField<Type>& Mphi = tMphi.ref();
2485 
2486  // Loop over field components
2487  if (M.hasDiag())
2488  {
2489  for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
2490  {
2491  scalarField psiCmpt(psi.primitiveField().component(cmpt));
2492  scalarField boundaryDiagCmpt(M.diag());
2493  M.addBoundaryDiag(boundaryDiagCmpt, cmpt);
2494  Mphi.primitiveFieldRef().replace(cmpt, -boundaryDiagCmpt*psiCmpt);
2495  }
2496  }
2497  else
2498  {
2499  Mphi.primitiveFieldRef() = Zero;
2500  }
2501 
2502  Mphi.primitiveFieldRef() +=
2503  M.lduMatrix::H(psi.primitiveField()) + M.source();
2504  M.addBoundarySource(Mphi.primitiveFieldRef());
2505 
2506  Mphi.primitiveFieldRef() /= -psi.mesh().V();
2507  Mphi.correctBoundaryConditions();
2508 
2509  return tMphi;
2510 }
2511 
2512 template<class Type>
2514 Foam::operator&
2515 (
2516  const fvMatrix<Type>& M,
2517  const tmp<DimensionedField<Type, fvMesh>>& tpsi
2518 )
2519 {
2520  tmp<VolField<Type>> tMpsi = M & tpsi();
2521  tpsi.clear();
2522  return tMpsi;
2523 }
2524 
2525 template<class Type>
2527 Foam::operator&
2528 (
2529  const fvMatrix<Type>& M,
2530  const tmp<VolField<Type>>& tpsi
2531 )
2532 {
2533  tmp<VolField<Type>> tMpsi = M & tpsi();
2534  tpsi.clear();
2535  return tMpsi;
2536 }
2537 
2538 template<class Type>
2540 Foam::operator&
2541 (
2542  const tmp<fvMatrix<Type>>& tM,
2543  const DimensionedField<Type, fvMesh>& psi
2544 )
2545 {
2546  tmp<VolField<Type>> tMpsi = tM() & psi;
2547  tM.clear();
2548  return tMpsi;
2549 }
2550 
2551 template<class Type>
2553 Foam::operator&
2554 (
2555  const tmp<fvMatrix<Type>>& tM,
2556  const tmp<DimensionedField<Type, fvMesh>>& tpsi
2557 )
2558 {
2559  tmp<VolField<Type>> tMpsi = tM() & tpsi();
2560  tM.clear();
2561  tpsi.clear();
2562  return tMpsi;
2563 }
2564 
2565 template<class Type>
2567 Foam::operator&
2568 (
2569  const tmp<fvMatrix<Type>>& tM,
2570  const tmp<VolField<Type>>& tpsi
2571 )
2572 {
2573  tmp<VolField<Type>> tMpsi = tM() & tpsi();
2574  tM.clear();
2575  tpsi.clear();
2576  return tMpsi;
2577 }
2578 
2579 
2580 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
2581 
2582 template<class Type>
2583 Foam::Ostream& Foam::operator<<(Ostream& os, const fvMatrix<Type>& fvm)
2584 {
2585  os << static_cast<const lduMatrix&>(fvm) << nl
2586  << fvm.dimensions_ << nl
2587  << fvm.source_ << nl
2588  << fvm.internalCoeffs_ << nl
2589  << fvm.boundaryCoeffs_ << endl;
2590 
2591  os.check("Ostream& operator<<(Ostream&, fvMatrix<Type>&");
2592 
2593  return os;
2594 }
2595 
2596 
2597 // * * * * * * * * * * * * * * * * Solvers * * * * * * * * * * * * * * * * * //
2598 
2599 #include "fvMatrixSolve.C"
2600 
2601 // ************************************************************************* //
EaEqn relax()
#define M(I)
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
static tmp< DimensionedField< Type, GeoMesh, PrimitiveField > > New(const word &name, const GeoMesh &mesh, const dimensionSet &, const PrimitiveField< Type > &)
Return a temporary field constructed from name, mesh,.
const dimensionSet & dimensions() const
Return dimensions.
const GeoMesh & mesh() const
Return mesh.
Generic field type.
Definition: FieldField.H:77
Pre-declare SubField and related Field type.
Definition: Field.H:83
void negate()
Negate this field.
Definition: Field.C:477
void updateCoeffs()
Update the boundary condition coefficients.
Generic GeometricField class.
Internal::FieldType & primitiveFieldRef()
Return a reference to the primitive field.
DimensionedField< Type, GeoMesh, PrimitiveField > Internal
Type of the internal field from which this GeometricField is derived.
void replace(const direction, const GeometricField< cmptType, GeoMesh, PrimitiveField2 > &)
Replace a component field of the field.
Boundary & boundaryFieldRef()
Return a reference to the boundary field.
const Internal::FieldType & primitiveField() const
Return a const-reference to the primitive field.
void correctBoundaryConditions()
Correct boundary field.
static tmp< GeometricField< Type, GeoMesh, PrimitiveField > > New(const word &name, const Internal &, const PtrList< Patch > &, const HashPtrTable< Source > &=HashPtrTable< Source >())
Return a temporary field constructed from name,.
const word & name() const
Return name.
Definition: IOobject.H:307
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:108
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
label size() const
Return the number of elements in the UList.
Definition: UListI.H:311
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:476
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:60
Dimension set for the base types.
Definition: dimensionSet.H:125
Generic dimensioned Type class.
const dimensionSet & dimensions() const
Return const reference to dimensions.
const word & name() const
Return const reference to name.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvMatrix.H:118
void operator-=(const fvMatrix< Type > &)
Definition: fvMatrix.C:1136
tmp< Field< Type > > DD() const
Return the matrix Type diagonal.
Definition: fvMatrix.C:783
tmp< volScalarField > A() const
Return the central coefficient.
Definition: fvMatrix.C:807
void addToInternalField(const labelUList &addr, const Field< Type2 > &pf, Field< Type2 > &intf) const
Add patch contribution to internal field.
Definition: fvMatrix.C:40
void setValue(const label celli, const Type &value)
Set solution in the given cell to the specified value.
Definition: fvMatrix.C:179
void boundaryManipulate(typename VolField< Type >::Boundary &values)
Manipulate based on a boundary field.
Definition: fvMatrix.C:761
void relax()
Relax matrix (for steady-state solution).
Definition: fvMatrix.C:753
tmp< volScalarField > H1() const
Return H(1)
Definition: fvMatrix.C:922
tmp< VolField< Type > > H() const
Return the H operation source.
Definition: fvMatrix.C:867
void operator+=(const fvMatrix< Type > &)
Definition: fvMatrix.C:1102
virtual ~fvMatrix()
Destructor.
Definition: fvMatrix.C:481
VolField< Type > & psi()
Definition: fvMatrix.H:289
tmp< SurfaceField< Type > > flux() const
Return the face-flux field from the matrix.
Definition: fvMatrix.C:963
void addCmptAvBoundaryDiag(scalarField &diag) const
Definition: fvMatrix.C:131
void addBoundarySource(Field< Type > &source, const bool couples=true) const
Definition: fvMatrix.C:147
fvMatrix(const VolField< Type > &, const dimensionSet &)
Construct given a field to solve for.
Definition: fvMatrix.C:285
tmp< volScalarField::Internal > Sp() const
Return the implicit source.
Definition: fvMatrix.C:846
void setReference(const label celli, const Type &value, const bool forceReference=false)
Set reference level for solution.
Definition: fvMatrix.C:562
scalar relaxationFactor() const
Return the relaxation factor for this equation.
Definition: fvMatrix.C:577
void addBoundaryDiag(scalarField &diag, const direction cmpt) const
Definition: fvMatrix.C:113
void negate()
Definition: fvMatrix.C:1087
void setValues(const labelUList &cells, const ListType< Type > &values)
Set solution in given cells to the specified values.
Definition: fvMatrix.C:501
tmp< fvMatrix< Type > > clone() const
Clone.
Definition: fvMatrix.C:469
tmp< VolInternalField< Type > > Su() const
Return the explicit source.
Definition: fvMatrix.C:828
tmp< scalarField > D() const
Return the matrix scalar diagonal.
Definition: fvMatrix.C:774
void subtractFromInternalField(const labelUList &addr, const Field< Type2 > &pf, Field< Type2 > &intf) const
Subtract patch contribution from internal field.
Definition: fvMatrix.C:77
const dimensionSet & dimensions() const
Definition: fvMatrix.H:302
void operator=(const fvMatrix< Type > &)
Definition: fvMatrix.C:1043
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:98
const labelUList & owner() const
Internal face owner.
Definition: fvMesh.H:490
const UCompactListList< label > & polyBFacePatches() const
Return poly-bFace-patch addressing.
Definition: fvMesh.C:986
const UCompactListList< label > & polyBFacePatchFaces() const
Return poly-bFace-patch-face addressing.
Definition: fvMesh.C:1062
const labelUList & neighbour() const
Internal face neighbour.
Definition: fvMesh.H:496
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:90
virtual bool coupled() const
Return true if this patch field is coupled.
Definition: fvPatchField.H:339
virtual tmp< Field< Type > > patchNeighbourField(const Pstream::commsTypes commsType=Pstream::commsTypes::blocking) const
Return patchField on the opposite patch of a coupled patch.
Definition: fvPatchField.H:447
lduMatrix is a general matrix class in which the coefficients are stored as three arrays,...
Definition: lduMatrix.H:80
tmp< scalarField > H1() const
tmp< Field< Type > > faceH(const Field< Type > &) const
void operator=(const lduMatrix &)
tmp< Field< Type > > H(const Field< Type > &) const
void operator*=(const scalarField &)
scalarField & diag()
Definition: lduMatrix.C:186
void operator/=(const scalarField &)
void operator+=(const lduMatrix &)
void operator-=(const lduMatrix &)
bool hasDiag() const
Definition: lduMatrix.H:580
Traits class for primitives.
Definition: pTraits.H:53
label nInternalFaces() const
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
const cellList & cells() const
Reference counter for various OpenFOAM components.
Definition: refCount.H:50
uint64_t eventNo() const
Event number at last update.
Definition: regIOobjectI.H:89
static bool finalIteration(const objectRegistry &registry)
Lookup solutionControl from the objectRegistry and return finalIter.
A class for managing temporary objects.
Definition: tmp.H:55
T * ptr() const
Return tmp pointer for reuse.
Definition: tmpI.H:221
void clear() const
If object pointer points to valid object:
Definition: tmpI.H:253
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
A class representing the concept of 0 used to avoid unnecessary manipulations for objects that are kn...
Definition: zero.H:50
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
Calculate the matrix for the first temporal derivative.
label patchi
const cellShapeList & cells
const fvPatchList & patches
const volScalarField & psi
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
#define InfoInFunction
Report an information message using Foam::Info.
const dimensionedScalar c
Speed of light in a vacuum.
tmp< fvMatrix< Type > > S(const Pair< tmp< volScalarField::Internal >> &, const VolField< Type > &)
tmp< fvMatrix< Type > > ddt(const VolField< Type > &vf)
Definition: fvmDdt.C:46
static const coefficient D("D", dimTemperature, 257.14)
static const coefficient B("B", dimless, 18.678)
static const coefficient A("A", dimPressure, 611.21)
const unitSet fraction
static const zero Zero
Definition: zero.H:97
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
tmp< DimensionedField< Type, GeoMesh, Field > > cmptMultiply(const DimensionedField< Type, GeoMesh, PrimitiveField1 > &df1, const DimensionedField< Type, GeoMesh, PrimitiveField2 > &df2)
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
void deleteDemandDrivenData(DataType *&dataPtr)
errorManip< error > abort(error &err)
Definition: errorManip.H:131
const dimensionSet & dimVolume
Definition: dimensions.C:150
void checkMethod(const fvMatrix< Type > &, const fvMatrix< Type > &, const char *)
Definition: fvMatrix.C:1421
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
void cmptMax(Field< typename Field< Type >::cmptType > &res, const UList< Type > &f)
void component(GeometricField< typename GeometricField< Type, GeoMesh, PrimitiveField1 >::cmptType, GeoMesh, PrimitiveField1 > &gcf, const GeometricField< Type, GeoMesh, PrimitiveField2 > &gf, const direction d)
void operator*=(Other &, const oneOrTmp< Type > &)
Multiply-assign with an object.
Definition: oneOrTmpI.H:168
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
typename VolField< Type >::Internal VolInternalField
Definition: volFieldsFwd.H:59
tmp< fvMatrix< Type > > correction(const fvMatrix< Type > &)
Return the correction form of the given matrix.
void cmptMin(Field< typename Field< Type >::cmptType > &res, const UList< Type > &f)
tmp< DimensionedField< typename DimensionedField< Type, GeoMesh, PrimitiveField >::cmptType, GeoMesh, Field >> cmptAv(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
Ostream & operator<<(Ostream &os, const fvConstraints &constraints)
error FatalError
tmp< DimensionedField< Type, GeoMesh, Field > > cmptMag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
void operator+=(fvMatrix< Type > &fvEqn, const CarrierEqn< Type > &cEqn)
Add to a finite-volume equation.
Definition: CarrierEqn.C:271
static const char nl
Definition: Ostream.H:297
void operator-=(fvMatrix< Type > &fvEqn, const CarrierEqn< Type > &cEqn)
Subtract from a finite-volume equation.
Definition: CarrierEqn.C:299
uint8_t direction
Definition: direction.H:45
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
dictionary fractions(initialConditions.subDict("fractions"))
faceListList boundary(nPatches)
Foam::surfaceFields.
conserve primitiveFieldRef()+