faMatrix.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2016-2017 Wikki Ltd
9  Copyright (C) 2019-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "areaFields.H"
30 #include "edgeFields.H"
34 #include "IndirectList.H"
35 #include "UniformList.H"
37 
38 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
39 
40 template<class Type>
41 template<class Type2>
43 (
44  const labelUList& addr,
45  const Field<Type2>& pf,
46  Field<Type2>& intf
47 ) const
48 {
49  if (addr.size() != pf.size())
50  {
52  << "addressing (" << addr.size()
53  << ") and field (" << pf.size() << ") are different sizes" << endl
54  << abort(FatalError);
55  }
56 
57  forAll(addr, faceI)
58  {
59  intf[addr[faceI]] += pf[faceI];
60  }
61 }
62 
63 
64 template<class Type>
65 template<class Type2>
67 (
68  const labelUList& addr,
69  const tmp<Field<Type2>>& tpf,
70  Field<Type2>& intf
71 ) const
72 {
73  addToInternalField(addr, tpf(), intf);
74  tpf.clear();
75 }
76 
77 
78 template<class Type>
79 template<class Type2>
81 (
82  const labelUList& addr,
83  const Field<Type2>& pf,
84  Field<Type2>& intf
85 ) const
86 {
87  if (addr.size() != pf.size())
88  {
90  << "addressing (" << addr.size()
91  << ") and field (" << pf.size() << ") are different sizes" << endl
92  << abort(FatalError);
93  }
94 
95  forAll(addr, faceI)
96  {
97  intf[addr[faceI]] -= pf[faceI];
98  }
99 }
100 
101 
102 template<class Type>
103 template<class Type2>
105 (
106  const labelUList& addr,
107  const tmp<Field<Type2>>& tpf,
108  Field<Type2>& intf
109 ) const
110 {
111  subtractFromInternalField(addr, tpf(), intf);
112  tpf.clear();
113 }
114 
115 
116 template<class Type>
118 (
119  scalarField& diag,
120  const direction solveCmpt
121 ) const
122 {
123  forAll(internalCoeffs_, patchI)
124  {
125  addToInternalField
126  (
127  lduAddr().patchAddr(patchI),
128  internalCoeffs_[patchI].component(solveCmpt),
130  );
131  }
132 }
133 
134 
135 template<class Type>
137 {
138  forAll(internalCoeffs_, patchI)
139  {
140  addToInternalField
141  (
142  lduAddr().patchAddr(patchI),
143  cmptAv(internalCoeffs_[patchI]),
144  diag
145  );
146  }
147 }
148 
149 
150 template<class Type>
152 (
153  Field<Type>& source,
154  const bool couples
155 ) const
156 {
157  forAll(psi_.boundaryField(), patchI)
158  {
159  const faPatchField<Type>& ptf = psi_.boundaryField()[patchI];
160  const Field<Type>& pbc = boundaryCoeffs_[patchI];
161 
162  if (!ptf.coupled())
163  {
164  addToInternalField(lduAddr().patchAddr(patchI), pbc, source);
165  }
166  else if (couples)
167  {
168  tmp<Field<Type>> tpnf = ptf.patchNeighbourField();
169  const Field<Type>& pnf = tpnf();
170 
171  const labelUList& addr = lduAddr().patchAddr(patchI);
172 
173  forAll(addr, facei)
174  {
175  source[addr[facei]] += cmptMultiply(pbc[facei], pnf[facei]);
176  }
177  }
178  }
179 }
180 
181 
182 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
183 
184 template<class Type>
186 (
188  const dimensionSet& ds
189 )
190 :
191  lduMatrix(psi.mesh()),
192  psi_(psi),
193  dimensions_(ds),
194  source_(psi.size(), Zero),
195  internalCoeffs_(psi.mesh().boundary().size()),
196  boundaryCoeffs_(psi.mesh().boundary().size()),
197  faceFluxCorrectionPtr_(nullptr)
198 {
200  << "constructing faMatrix<Type> for field " << psi_.name()
201  << endl;
202 
203  // Initialise coupling coefficients
204  forAll(psi.mesh().boundary(), patchi)
205  {
206  internalCoeffs_.set
207  (
208  patchi,
209  new Field<Type>(psi.mesh().boundary()[patchi].size(), Zero)
210  );
211 
212  boundaryCoeffs_.set
213  (
214  patchi,
215  new Field<Type>(psi.mesh().boundary()[patchi].size(), Zero)
216  );
217  }
218 
219  // Update the boundary coefficients of psi without changing its event No.
220  auto& psiRef =
221  const_cast<GeometricField<Type, faPatchField, areaMesh>&>(psi_);
222 
223  const label currentStatePsi = psiRef.eventNo();
224  psiRef.boundaryFieldRef().updateCoeffs();
225  psiRef.eventNo() = currentStatePsi;
226 }
227 
228 
229 template<class Type>
231 :
232  lduMatrix(fam),
233  psi_(fam.psi_),
234  dimensions_(fam.dimensions_),
235  source_(fam.source_),
236  internalCoeffs_(fam.internalCoeffs_),
237  boundaryCoeffs_(fam.boundaryCoeffs_),
238  faceFluxCorrectionPtr_(nullptr)
239 {
241  << "Copying faMatrix<Type> for field " << psi_.name() << endl;
242 
243  if (fam.faceFluxCorrectionPtr_)
244  {
245  faceFluxCorrectionPtr_ =
247  (
248  *(fam.faceFluxCorrectionPtr_)
249  );
250  }
251 }
252 
253 
254 template<class Type>
255 Foam::faMatrix<Type>::faMatrix(const tmp<faMatrix<Type>>& tmat)
256 :
257  lduMatrix(tmat.constCast(), tmat.movable()),
258  psi_(tmat().psi_),
259  dimensions_(tmat().dimensions_),
260  source_(tmat.constCast().source_, tmat.movable()),
261  internalCoeffs_(tmat.constCast().internalCoeffs_, tmat.movable()),
262  boundaryCoeffs_(tmat.constCast().boundaryCoeffs_, tmat.movable()),
263  faceFluxCorrectionPtr_(nullptr)
264 {
266  << "Copy/Move faMatrix<Type> for field " << psi_.name() << endl;
267 
268  if (tmat().faceFluxCorrectionPtr_)
269  {
270  if (tmat.movable())
271  {
272  faceFluxCorrectionPtr_ = tmat().faceFluxCorrectionPtr_;
273  tmat().faceFluxCorrectionPtr_ = nullptr;
274  }
275  else
276  {
277  faceFluxCorrectionPtr_ =
278  new GeometricField<Type, faePatchField, edgeMesh>
279  (
280  *(tmat().faceFluxCorrectionPtr_)
281  );
282  }
283  }
284 
285  tmat.clear();
286 }
287 
288 
289 // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * * //
290 
291 template<class Type>
293 {
295  << "Destroying faMatrix<Type> for field " << psi_.name() << endl;
296 
297  deleteDemandDrivenData(faceFluxCorrectionPtr_);
298 }
300 
301 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
302 
303 template<class Type>
304 template<template<class> class ListType>
306 (
307  const labelUList& faceLabels,
308  const ListType<Type>& values
309 )
310 {
311 #if 0 /* Specific to foam-extend */
312  // Record face labels of eliminated equations
313  for (const label i : faceLabels)
314  {
315  this->eliminatedEqns().insert(i);
316  }
317 #endif
318 
319  const faMesh& mesh = psi_.mesh();
320 
321  const labelListList& edges = mesh.patch().faceEdges();
322  const labelUList& own = mesh.owner();
323  const labelUList& nei = mesh.neighbour();
324 
325  scalarField& Diag = diag();
326  Field<Type>& psi =
327  const_cast
328  <
330  >(psi_).primitiveFieldRef();
331 
332  // Following actions:
333  // - adjust local field psi
334  // - set local matrix to be diagonal (so adjust source)
335  // - cut connections to neighbours
336  // - make (on non-adjusted cells) contribution explicit
337 
338  if (symmetric() || asymmetric())
339  {
340  forAll(faceLabels, i)
341  {
342  const label facei = faceLabels[i];
343  const Type& value = values[i];
344 
345  for (const label edgei : edges[facei])
346  {
347  if (mesh.isInternalEdge(edgei))
348  {
349  if (symmetric())
350  {
351  if (facei == own[edgei])
352  {
353  source_[nei[edgei]] -= upper()[edgei]*value;
354  }
355  else
356  {
357  source_[own[edgei]] -= upper()[edgei]*value;
358  }
359 
360  upper()[edgei] = 0.0;
361  }
362  else
363  {
364  if (facei == own[edgei])
365  {
366  source_[nei[edgei]] -= lower()[edgei]*value;
367  }
368  else
369  {
370  source_[own[edgei]] -= upper()[edgei]*value;
371  }
372 
373  upper()[edgei] = 0.0;
374  lower()[edgei] = 0.0;
375  }
376  }
377  else
378  {
379  const label patchi = mesh.boundary().whichPatch(edgei);
380 
381  if (internalCoeffs_[patchi].size())
382  {
383  const label patchEdgei =
384  mesh.boundary()[patchi].whichEdge(edgei);
385 
386  internalCoeffs_[patchi][patchEdgei] = Zero;
387  boundaryCoeffs_[patchi][patchEdgei] = Zero;
388  }
389  }
390  }
391  }
392  }
393 
394  // Note: above loop might have affected source terms on adjusted cells
395  // so make sure to adjust them afterwards
396  forAll(faceLabels, i)
397  {
398  const label facei = faceLabels[i];
399  const Type& value = values[i];
400 
401  psi[facei] = value;
402  source_[facei] = value*Diag[facei];
403  }
404 }
405 
406 
407 template<class Type>
409 (
410  const labelUList& faceLabels,
411  const Type& value
412 )
413 {
414  this->setValuesFromList(faceLabels, UniformList<Type>(value));
415 }
416 
417 
418 template<class Type>
420 (
421  const labelUList& faceLabels,
422  const UList<Type>& values
423 )
424 {
425  this->setValuesFromList(faceLabels, values);
426 }
427 
428 
429 template<class Type>
431 (
432  const labelUList& faceLabels,
434 )
435 {
436  this->setValuesFromList(faceLabels, values);
437 }
438 
439 
440 template<class Type>
442 (
443  const label facei,
444  const Type& value,
445  const bool forceReference
446 )
447 {
448  if ((forceReference || psi_.needReference()) && facei >= 0)
449  {
450  if (Pstream::master())
451  {
452  source()[facei] += diag()[facei]*value;
453  diag()[facei] += diag()[facei];
454  }
455  }
456 }
457 
458 
459 template<class Type>
461 (
462  const labelUList& faceLabels,
463  const Type& value,
464  const bool forceReference
465 )
466 {
467  if (forceReference || psi_.needReference())
468  {
469  forAll(faceLabels, facei)
470  {
471  const label faceId = faceLabels[facei];
472  if (faceId >= 0)
473  {
474  source()[faceId] += diag()[faceId]*value;
475  diag()[faceId] += diag()[faceId];
476  }
477  }
478  }
479 }
480 
481 
482 template<class Type>
484 (
485  const labelUList& faceLabels,
486  const UList<Type>& values,
487  const bool forceReference
488 )
489 {
490  if (forceReference || psi_.needReference())
491  {
492  forAll(faceLabels, facei)
493  {
494  const label faceId = faceLabels[facei];
495  if (faceId >= 0)
496  {
497  source()[faceId] += diag()[faceId]*values[facei];
498  diag()[faceId] += diag()[faceId];
499  }
500  }
501  }
502 }
503 
504 
505 template<class Type>
506 void Foam::faMatrix<Type>::relax(const scalar alpha)
507 {
508  if (alpha <= 0)
509  {
510  return;
511  }
512 
513  Field<Type>& S = source();
514  scalarField& D = diag();
515 
516  // Store the current unrelaxed diagonal for use in updating the source
517  scalarField D0(D);
518 
519  // Calculate the sum-mag off-diagonal from the interior faces
520  scalarField sumOff(D.size(), Zero);
521  sumMagOffDiag(sumOff);
522 
523  // Handle the boundary contributions to the diagonal
524  forAll(psi_.boundaryField(), patchI)
525  {
526  const faPatchField<Type>& ptf = psi_.boundaryField()[patchI];
527 
528  if (ptf.size())
529  {
530  const labelUList& pa = lduAddr().patchAddr(patchI);
531  Field<Type>& iCoeffs = internalCoeffs_[patchI];
532 
533  if (ptf.coupled())
534  {
535  const Field<Type>& pCoeffs = boundaryCoeffs_[patchI];
536 
537  // For coupled boundaries add the diagonal and
538  // off-diagonal contributions
539  forAll(pa, face)
540  {
541  D[pa[face]] += component(iCoeffs[face], 0);
542  sumOff[pa[face]] += mag(component(pCoeffs[face], 0));
543  }
544  }
545  else
546  {
547  // For non-coupled boundaries subtract the diagonal
548  // contribution off-diagonal sum which avoids having to remove
549  // it from the diagonal later.
550  // Also add the source contribution from the relaxation
551  forAll(pa, face)
552  {
553  Type iCoeff0 = iCoeffs[face];
554  iCoeffs[face] = cmptMag(iCoeffs[face]);
555  sumOff[pa[face]] -= cmptMin(iCoeffs[face]);
556  iCoeffs[face] /= alpha;
557  S[pa[face]] +=
558  cmptMultiply(iCoeffs[face] - iCoeff0, psi_[pa[face]]);
559  }
560  }
561  }
562  }
563 
564  // Ensure the matrix is diagonally dominant...
565  max(D, D, sumOff);
566 
567  // ... then relax
568  D /= alpha;
569 
570  // Now remove the diagonal contribution from coupled boundaries
571  forAll(psi_.boundaryField(), patchI)
572  {
573  const faPatchField<Type>& ptf = psi_.boundaryField()[patchI];
574 
575  if (ptf.size())
576  {
577  const labelUList& pa = lduAddr().patchAddr(patchI);
578  Field<Type>& iCoeffs = internalCoeffs_[patchI];
579 
580  if (ptf.coupled())
581  {
582  forAll(pa, face)
583  {
584  D[pa[face]] -= component(iCoeffs[face], 0);
585  }
586  }
587  }
588  }
590  // Finally add the relaxation contribution to the source.
591  S += (D - D0)*psi_.primitiveField();
592 }
593 
594 
595 template<class Type>
597 {
598  scalar relaxCoeff = 0;
599 
600  if (psi_.mesh().relaxEquation(psi_.name(), relaxCoeff))
601  {
602  relax(relaxCoeff);
603  }
604  else
605  {
607  << "No relaxation specified for field " << psi_.name() << nl;
608  }
609 }
610 
611 
612 template<class Type>
614 {
615  auto tdiag = tmp<scalarField>::New(diag());
616  addCmptAvBoundaryDiag(tdiag.ref());
617  return tdiag;
618 }
619 
620 
621 template<class Type>
623 {
624  auto tAphi = areaScalarField::New
625  (
626  "A(" + psi_.name() + ')',
627  psi_.mesh(),
628  dimensions_/psi_.dimensions()/dimArea,
630  );
631 
632  tAphi.ref().primitiveFieldRef() = D()/psi_.mesh().S();
633  tAphi.ref().correctBoundaryConditions();
635  return tAphi;
636 }
637 
638 
639 template<class Type>
642 {
644  (
645  "H(" + psi_.name() + ')',
646  psi_.mesh(),
647  dimensions_/dimArea,
649  );
650  auto& Hphi = tHphi.ref();
651 
652  // Loop over field components
653  for (direction cmpt=0; cmpt<Type::nComponents; ++cmpt)
654  {
655  scalarField psiCmpt(psi_.primitiveField().component(cmpt));
656 
657  scalarField boundaryDiagCmpt(psi_.size(), Zero);
658  addBoundaryDiag(boundaryDiagCmpt, cmpt);
659  boundaryDiagCmpt.negate();
660  addCmptAvBoundaryDiag(boundaryDiagCmpt);
661 
662  Hphi.primitiveFieldRef().replace(cmpt, boundaryDiagCmpt*psiCmpt);
663  }
664 
665  Hphi.primitiveFieldRef() += lduMatrix::H(psi_.primitiveField()) + source_;
666  addBoundarySource(Hphi.primitiveFieldRef());
667 
668  Hphi.primitiveFieldRef() /= psi_.mesh().S();
671  return tHphi;
672 }
673 
674 
675 template<class Type>
678 {
679  if (!psi_.mesh().fluxRequired(psi_.name()))
680  {
682  << "flux requested but " << psi_.name()
683  << " not specified in the fluxRequired sub-dictionary of faSchemes"
684  << abort(FatalError);
685  }
686 
688  (
689  "flux(" + psi_.name() + ')',
690  psi_.mesh(),
691  dimensions()
692  );
693  auto& fieldFlux = tfieldFlux.ref();
694 
695  for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; ++cmpt)
696  {
697  fieldFlux.primitiveFieldRef().replace
698  (
699  cmpt,
700  lduMatrix::faceH(psi_.primitiveField().component(cmpt))
701  );
702  }
703 
704  FieldField<Field, Type> InternalContrib = internalCoeffs_;
705 
706  forAll(InternalContrib, patchI)
707  {
708  InternalContrib[patchI] =
710  (
711  InternalContrib[patchI],
712  psi_.boundaryField()[patchI].patchInternalField()
713  );
714  }
715 
716  FieldField<Field, Type> NeighbourContrib = boundaryCoeffs_;
717 
718  forAll(NeighbourContrib, patchI)
719  {
720  if (psi_.boundaryField()[patchI].coupled())
721  {
722  NeighbourContrib[patchI] =
724  (
725  NeighbourContrib[patchI],
726  psi_.boundaryField()[patchI].patchNeighbourField()
727  );
728  }
729  }
730 
731  forAll(fieldFlux.boundaryField(), patchI)
732  {
733  fieldFlux.boundaryFieldRef()[patchI] =
734  InternalContrib[patchI] - NeighbourContrib[patchI];
735  }
736 
737  if (faceFluxCorrectionPtr_)
738  {
739  fieldFlux += *faceFluxCorrectionPtr_;
740  }
742  return tfieldFlux;
743 }
744 
745 
746 template<class Type>
748 (
749  const word& name
750 ) const
751 {
752  return psi_.mesh().solverDict(name);
753 }
754 
755 
756 template<class Type>
758 {
759  return psi_.mesh().solverDict
760  (
761  psi_.name()
762  );
763 }
764 
765 
766 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
767 
768 template<class Type>
770 {
771  if (this == &famv)
772  {
773  return; // Self-assignment is a no-op
774  }
775 
776  if (&psi_ != &(famv.psi_))
777  {
779  << "different fields"
780  << abort(FatalError);
781  }
782 
783  lduMatrix::operator=(famv);
784  source_ = famv.source_;
785  internalCoeffs_ = famv.internalCoeffs_;
786  boundaryCoeffs_ = famv.boundaryCoeffs_;
787 
788  if (faceFluxCorrectionPtr_ && famv.faceFluxCorrectionPtr_)
789  {
790  *faceFluxCorrectionPtr_ = *famv.faceFluxCorrectionPtr_;
791  }
792  else if (famv.faceFluxCorrectionPtr_)
793  {
794  faceFluxCorrectionPtr_ =
796  (*famv.faceFluxCorrectionPtr_);
797  }
798 }
799 
800 
801 template<class Type>
802 void Foam::faMatrix<Type>::operator=(const tmp<faMatrix<Type>>& tfamv)
803 {
804  operator=(tfamv());
805  tfamv.clear();
806 }
807 
808 
809 template<class Type>
811 {
813  source_.negate();
814  internalCoeffs_.negate();
815  boundaryCoeffs_.negate();
816 
817  if (faceFluxCorrectionPtr_)
818  {
819  faceFluxCorrectionPtr_->negate();
820  }
821 }
822 
823 
824 template<class Type>
825 void Foam::faMatrix<Type>::operator+=(const faMatrix<Type>& famv)
826 {
827  checkMethod(*this, famv, "+=");
828 
829  dimensions_ += famv.dimensions_;
830  lduMatrix::operator+=(famv);
831  source_ += famv.source_;
832  internalCoeffs_ += famv.internalCoeffs_;
833  boundaryCoeffs_ += famv.boundaryCoeffs_;
834 
835  if (faceFluxCorrectionPtr_ && famv.faceFluxCorrectionPtr_)
836  {
837  *faceFluxCorrectionPtr_ += *famv.faceFluxCorrectionPtr_;
838  }
839  else if (famv.faceFluxCorrectionPtr_)
840  {
841  faceFluxCorrectionPtr_ = new
842  GeometricField<Type, faePatchField, edgeMesh>
843  (
844  *famv.faceFluxCorrectionPtr_
845  );
846  }
847 }
848 
849 
850 template<class Type>
851 void Foam::faMatrix<Type>::operator+=(const tmp<faMatrix<Type>>& tfamv)
852 {
853  operator+=(tfamv());
854  tfamv.clear();
855 }
856 
857 
858 template<class Type>
860 {
861  checkMethod(*this, famv, "+=");
862 
863  dimensions_ -= famv.dimensions_;
864  lduMatrix::operator-=(famv);
865  source_ -= famv.source_;
866  internalCoeffs_ -= famv.internalCoeffs_;
867  boundaryCoeffs_ -= famv.boundaryCoeffs_;
868 
869  if (faceFluxCorrectionPtr_ && famv.faceFluxCorrectionPtr_)
870  {
871  *faceFluxCorrectionPtr_ -= *famv.faceFluxCorrectionPtr_;
872  }
873  else if (famv.faceFluxCorrectionPtr_)
874  {
875  faceFluxCorrectionPtr_ =
877  (-*famv.faceFluxCorrectionPtr_);
878  }
879 }
880 
881 
882 template<class Type>
883 void Foam::faMatrix<Type>::operator-=(const tmp<faMatrix<Type>>& tfamv)
884 {
885  operator-=(tfamv());
886  tfamv.clear();
887 }
888 
889 
890 template<class Type>
892 (
894 )
895 {
896  checkMethod(*this, su, "+=");
897  source() -= su.mesh().S()*su.field();
898 }
899 
900 
901 template<class Type>
903 (
905 )
906 {
907  operator+=(tsu());
908  tsu.clear();
909 }
910 
911 
912 template<class Type>
914 (
916 )
917 {
918  operator+=(tsu());
919  tsu.clear();
920 }
921 
922 
923 template<class Type>
925 (
927 )
928 {
929  checkMethod(*this, su, "-=");
930  source() += su.mesh().S()*su.field();
931 }
932 
933 
934 template<class Type>
936 (
938 )
939 {
940  operator-=(tsu());
941  tsu.clear();
942 }
943 
944 
945 template<class Type>
947 (
949 )
950 {
951  operator-=(tsu());
952  tsu.clear();
953 }
954 
955 
956 template<class Type>
958 (
959  const dimensioned<Type>& su
960 )
961 {
962  source() -= psi().mesh().S()*su;
963 }
964 
965 
966 template<class Type>
968 (
969  const dimensioned<Type>& su
970 )
971 {
972  source() += psi().mesh().S()*su;
973 }
974 
975 
976 template<class Type>
978 (
979  const areaScalarField::Internal& dsf
980 )
981 {
982  dimensions_ *= dsf.dimensions();
983  lduMatrix::operator*=(dsf.field());
984  source_ *= dsf.field();
985 
986  forAll(boundaryCoeffs_, patchi)
987  {
988  const scalarField pisf
989  (
990  dsf.mesh().boundary()[patchi].patchInternalField(dsf.field())
991  );
992  internalCoeffs_[patchi] *= pisf;
993  boundaryCoeffs_[patchi] *= pisf;
994  }
995 
996  if (faceFluxCorrectionPtr_)
997  {
999  << "cannot scale a matrix containing a faceFluxCorrection"
1001  }
1002 }
1003 
1004 
1005 template<class Type>
1007 (
1008  const tmp<areaScalarField::Internal>& tfld
1009 )
1010 {
1011  operator*=(tfld());
1012  tfld.clear();
1013 }
1014 
1015 
1016 template<class Type>
1018 (
1019  const tmp<areaScalarField>& tfld
1020 )
1021 {
1022  operator*=(tfld());
1023  tfld.clear();
1024 }
1025 
1026 
1027 template<class Type>
1029 (
1030  const dimensioned<scalar>& ds
1031 )
1032 {
1033  dimensions_ *= ds.dimensions();
1034  lduMatrix::operator*=(ds.value());
1035  source_ *= ds.value();
1036  internalCoeffs_ *= ds.value();
1037  boundaryCoeffs_ *= ds.value();
1038 
1039  if (faceFluxCorrectionPtr_)
1040  {
1041  *faceFluxCorrectionPtr_ *= ds.value();
1042  }
1044 
1045 
1046 // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
1047 
1048 template<class Type>
1049 void Foam::checkMethod
1050 (
1051  const faMatrix<Type>& mat1,
1052  const faMatrix<Type>& mat2,
1053  const char* op
1054 )
1055 {
1056  if (&mat1.psi() != &mat2.psi())
1057  {
1059  << "Incompatible fields for operation\n "
1060  << "[" << mat1.psi().name() << "] "
1061  << op
1062  << " [" << mat2.psi().name() << "]"
1063  << abort(FatalError);
1064  }
1065 
1066  if
1067  (
1069  && mat1.dimensions() != mat2.dimensions()
1070  )
1071  {
1073  << "Incompatible dimensions for operation\n "
1074  << "[" << mat1.psi().name() << mat1.dimensions()/dimArea << " ] "
1075  << op
1076  << " [" << mat2.psi().name() << mat2.dimensions()/dimArea << " ]"
1078  }
1079 }
1080 
1081 
1082 template<class Type>
1083 void Foam::checkMethod
1084 (
1085  const faMatrix<Type>& mat,
1086  const DimensionedField<Type, areaMesh>& fld,
1087  const char* op
1088 )
1089 {
1090  if
1091  (
1093  && mat.dimensions()/dimArea != fld.dimensions()
1094  )
1095  {
1097  << "Incompatible dimensions for operation\n "
1098  << "[" << mat.psi().name() << mat.dimensions()/dimArea << " ] "
1099  << op
1100  << " [" << fld.name() << fld.dimensions() << " ]"
1102  }
1103 }
1104 
1105 
1106 template<class Type>
1107 void Foam::checkMethod
1108 (
1109  const faMatrix<Type>& mat,
1110  const dimensioned<Type>& dt,
1111  const char* op
1112 )
1113 {
1114  if
1115  (
1117  && mat.dimensions()/dimArea != dt.dimensions()
1118  )
1119  {
1121  << "Incompatible dimensions for operation\n "
1122  << "[" << mat.psi().name() << mat.dimensions()/dimArea << " ] "
1123  << op
1124  << " [" << dt.name() << dt.dimensions() << " ]"
1125  << abort(FatalError);
1126  }
1127 }
1128 
1129 
1130 template<class Type>
1132 (
1133  faMatrix<Type>& mat,
1134  const dictionary& solverControls
1135 )
1136 {
1137  return mat.solve(solverControls);
1138 }
1139 
1140 
1141 template<class Type>
1143 (
1144  const tmp<faMatrix<Type>>& tmat,
1145  const dictionary& solverControls
1146 )
1147 {
1148  SolverPerformance<Type> solverPerf(tmat.constCast().solve(solverControls));
1149 
1150  tmat.clear();
1151 
1152  return solverPerf;
1153 }
1154 
1155 
1156 template<class Type>
1158 (
1159  faMatrix<Type>& mat,
1160  const word& name
1161 )
1162 {
1163  return mat.solve(name);
1164 }
1165 
1166 
1167 template<class Type>
1169 (
1170  const tmp<faMatrix<Type>>& tmat,
1171  const word& name
1172 )
1173 {
1174  SolverPerformance<Type> solverPerf(tmat.constCast().solve(name));
1175 
1176  tmat.clear();
1177 
1178  return solverPerf;
1179 }
1180 
1181 
1182 template<class Type>
1183 Foam::SolverPerformance<Type> Foam::solve(faMatrix<Type>& mat)
1184 {
1185  return mat.solve();
1186 }
1187 
1188 
1189 template<class Type>
1190 Foam::SolverPerformance<Type> Foam::solve(const tmp<faMatrix<Type>>& tmat)
1191 {
1192  SolverPerformance<Type> solverPerf(tmat.constCast().solve());
1193 
1194  tmat.clear();
1195 
1196  return solverPerf;
1197 }
1198 
1199 
1200 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
1201 
1202 template<class Type>
1203 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1204 (
1205  const faMatrix<Type>& A,
1206  const faMatrix<Type>& B
1207 )
1208 {
1209  checkMethod(A, B, "+");
1210  tmp<faMatrix<Type>> tC(new faMatrix<Type>(A));
1211  tC.ref() += B;
1212  return tC;
1213 }
1214 
1215 
1216 template<class Type>
1217 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1218 (
1219  const tmp<faMatrix<Type>>& tA,
1220  const faMatrix<Type>& B
1221 )
1222 {
1223  checkMethod(tA(), B, "+");
1224  tmp<faMatrix<Type>> tC(tA.ptr());
1225  tC.ref() += B;
1226  return tC;
1227 }
1228 
1229 
1230 template<class Type>
1231 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1232 (
1233  const faMatrix<Type>& A,
1234  const tmp<faMatrix<Type>>& tB
1235 )
1236 {
1237  checkMethod(A, tB(), "+");
1238  tmp<faMatrix<Type>> tC(tB.ptr());
1239  tC.ref() += A;
1240  return tC;
1241 }
1242 
1243 
1244 template<class Type>
1245 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1246 (
1247  const tmp<faMatrix<Type>>& tA,
1248  const tmp<faMatrix<Type>>& tB
1249 )
1250 {
1251  checkMethod(tA(), tB(), "+");
1252  tmp<faMatrix<Type>> tC(tA.ptr());
1253  tC.ref() += tB();
1254  tB.clear();
1255  return tC;
1256 }
1257 
1258 
1259 template<class Type>
1260 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1261 (
1262  const faMatrix<Type>& A
1263 )
1264 {
1265  tmp<faMatrix<Type>> tC(new faMatrix<Type>(A));
1266  tC.ref().negate();
1267  return tC;
1268 }
1269 
1270 
1271 template<class Type>
1272 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1273 (
1274  const tmp<faMatrix<Type>>& tA
1275 )
1276 {
1277  tmp<faMatrix<Type>> tC(tA.ptr());
1278  tC.ref().negate();
1279  return tC;
1280 }
1281 
1282 
1283 template<class Type>
1284 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1285 (
1286  const faMatrix<Type>& A,
1287  const faMatrix<Type>& B
1288 )
1289 {
1290  checkMethod(A, B, "-");
1291  tmp<faMatrix<Type>> tC(new faMatrix<Type>(A));
1292  tC.ref() -= B;
1293  return tC;
1294 }
1295 
1296 
1297 template<class Type>
1298 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1299 (
1300  const tmp<faMatrix<Type>>& tA,
1301  const faMatrix<Type>& B
1302 )
1303 {
1304  checkMethod(tA(), B, "-");
1305  tmp<faMatrix<Type>> tC(tA.ptr());
1306  tC.ref() -= B;
1307  return tC;
1308 }
1309 
1310 
1311 template<class Type>
1312 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1313 (
1314  const faMatrix<Type>& A,
1315  const tmp<faMatrix<Type>>& tB
1316 )
1317 {
1318  checkMethod(A, tB(), "-");
1319  tmp<faMatrix<Type>> tC(tB.ptr());
1320  tC.ref() -= A;
1321  tC.ref().negate();
1322  return tC;
1323 }
1324 
1325 
1326 template<class Type>
1327 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1328 (
1329  const tmp<faMatrix<Type>>& tA,
1330  const tmp<faMatrix<Type>>& tB
1331 )
1332 {
1333  checkMethod(tA(), tB(), "-");
1334  tmp<faMatrix<Type>> tC(tA.ptr());
1335  tC.ref() -= tB();
1336  tB.clear();
1337  return tC;
1338 }
1339 
1340 
1341 template<class Type>
1342 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1343 (
1344  const faMatrix<Type>& A,
1345  const faMatrix<Type>& B
1346 )
1347 {
1348  checkMethod(A, B, "==");
1349  return (A - B);
1350 }
1351 
1352 
1353 template<class Type>
1354 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1355 (
1356  const tmp<faMatrix<Type>>& tA,
1357  const faMatrix<Type>& B
1358 )
1359 {
1360  checkMethod(tA(), B, "==");
1361  return (tA - B);
1362 }
1363 
1364 
1365 template<class Type>
1366 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1367 (
1368  const faMatrix<Type>& A,
1369  const tmp<faMatrix<Type>>& tB
1370 )
1371 {
1372  checkMethod(A, tB(), "==");
1373  return (A - tB);
1374 }
1375 
1376 
1377 template<class Type>
1378 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1379 (
1380  const tmp<faMatrix<Type>>& tA,
1381  const tmp<faMatrix<Type>>& tB
1382 )
1383 {
1384  checkMethod(tA(), tB(), "==");
1385  return (tA - tB);
1386 }
1387 
1388 
1389 template<class Type>
1390 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1391 (
1392  const faMatrix<Type>& A,
1393  const DimensionedField<Type, areaMesh>& su
1394 )
1395 {
1396  checkMethod(A, su, "+");
1397  auto tC(A.clone());
1398  tC.ref().source() -= su.mesh().S()*su.field();
1399  return tC;
1400 }
1401 
1402 
1403 template<class Type>
1404 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1405 (
1406  const faMatrix<Type>& A,
1407  const tmp<DimensionedField<Type, areaMesh>>& tsu
1408 )
1409 {
1410  checkMethod(A, tsu(), "+");
1411  auto tC(A.clone());
1412  tC.ref().source() -= tsu().mesh().S()*tsu().field();
1413  tsu.clear();
1414  return tC;
1415 }
1416 
1417 
1418 template<class Type>
1419 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1420 (
1421  const faMatrix<Type>& A,
1422  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tsu
1423 )
1424 {
1425  checkMethod(A, tsu(), "+");
1426  auto tC(A.clone());
1427  tC.ref().source() -= tsu().mesh().S()*tsu().primitiveField();
1428  tsu.clear();
1429  return tC;
1430 }
1431 
1432 
1433 template<class Type>
1434 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1435 (
1436  const tmp<faMatrix<Type>>& tA,
1437  const DimensionedField<Type, areaMesh>& su
1438 )
1439 {
1440  checkMethod(tA(), su, "+");
1441  tmp<faMatrix<Type>> tC(tA.ptr());
1442  tC.ref().source() -= su.mesh().S()*su.field();
1443  return tC;
1444 }
1445 
1446 
1447 template<class Type>
1448 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1449 (
1450  const tmp<faMatrix<Type>>& tA,
1451  const tmp<DimensionedField<Type, areaMesh>>& tsu
1452 )
1453 {
1454  checkMethod(tA(), tsu(), "+");
1455  tmp<faMatrix<Type>> tC(tA.ptr());
1456  tC.ref().source() -= tsu().mesh().S()*tsu().field();
1457  tsu.clear();
1458  return tC;
1459 }
1460 
1461 
1462 template<class Type>
1463 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1464 (
1465  const tmp<faMatrix<Type>>& tA,
1466  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tsu
1467 )
1468 {
1469  checkMethod(tA(), tsu(), "+");
1470  tmp<faMatrix<Type>> tC(tA.ptr());
1471  tC.ref().source() -= tsu().mesh().S()*tsu().primitiveField();
1472  tsu.clear();
1473  return tC;
1474 }
1475 
1476 
1477 template<class Type>
1478 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1479 (
1480  const DimensionedField<Type, areaMesh>& su,
1481  const faMatrix<Type>& A
1482 )
1483 {
1484  checkMethod(A, su, "+");
1485  auto tC(A.clone());
1486  tC.ref().source() -= su.mesh().S()*su.field();
1487  return tC;
1488 }
1489 
1490 
1491 template<class Type>
1492 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1493 (
1494  const tmp<DimensionedField<Type, areaMesh>>& tsu,
1495  const faMatrix<Type>& A
1496 )
1497 {
1498  checkMethod(A, tsu(), "+");
1499  auto tC(A.clone());
1500  tC.ref().source() -= tsu().mesh().S()*tsu().field();
1501  tsu.clear();
1502  return tC;
1503 }
1504 
1505 
1506 template<class Type>
1507 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1508 (
1509  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tsu,
1510  const faMatrix<Type>& A
1511 )
1512 {
1513  checkMethod(A, tsu(), "+");
1514  auto tC(A.clone());
1515  tC.ref().source() -= tsu().mesh().S()*tsu().primitiveField();
1516  tsu.clear();
1517  return tC;
1518 }
1519 
1520 
1521 template<class Type>
1522 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1523 (
1524  const DimensionedField<Type, areaMesh>& su,
1525  const tmp<faMatrix<Type>>& tA
1526 )
1527 {
1528  checkMethod(tA(), su, "+");
1529  tmp<faMatrix<Type>> tC(tA.ptr());
1530  tC.ref().source() -= su.mesh().S()*su.field();
1531  return tC;
1532 }
1533 
1534 
1535 template<class Type>
1536 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1537 (
1538  const tmp<DimensionedField<Type, areaMesh>>& tsu,
1539  const tmp<faMatrix<Type>>& tA
1540 )
1541 {
1542  checkMethod(tA(), tsu(), "+");
1543  tmp<faMatrix<Type>> tC(tA.ptr());
1544  tC.ref().source() -= tsu().mesh().S()*tsu().field();
1545  tsu.clear();
1546  return tC;
1547 }
1548 
1549 
1550 template<class Type>
1551 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1552 (
1553  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tsu,
1554  const tmp<faMatrix<Type>>& tA
1555 )
1556 {
1557  checkMethod(tA(), tsu(), "+");
1558  tmp<faMatrix<Type>> tC(tA.ptr());
1559  tC.ref().source() -= tsu().mesh().S()*tsu().primitiveField();
1560  tsu.clear();
1561  return tC;
1562 }
1563 
1564 
1565 template<class Type>
1566 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1567 (
1568  const faMatrix<Type>& A,
1569  const DimensionedField<Type, areaMesh>& su
1570 )
1571 {
1572  checkMethod(A, su, "-");
1573  auto tC(A.clone());
1574  tC.ref().source() += su.mesh().S()*su.field();
1575  return tC;
1576 }
1577 
1578 
1579 template<class Type>
1580 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1581 (
1582  const faMatrix<Type>& A,
1583  const tmp<DimensionedField<Type, areaMesh>>& tsu
1584 )
1585 {
1586  checkMethod(A, tsu(), "-");
1587  auto tC(A.clone());
1588  tC.ref().source() += tsu().mesh().S()*tsu().field();
1589  tsu.clear();
1590  return tC;
1591 }
1592 
1593 
1594 template<class Type>
1595 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1596 (
1597  const faMatrix<Type>& A,
1598  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tsu
1599 )
1600 {
1601  checkMethod(A, tsu(), "-");
1602  auto tC(A.clone());
1603  tC.ref().source() += tsu().mesh().S()*tsu().primitiveField();
1604  tsu.clear();
1605  return tC;
1606 }
1607 
1608 
1609 template<class Type>
1610 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1611 (
1612  const tmp<faMatrix<Type>>& tA,
1613  const DimensionedField<Type, areaMesh>& su
1614 )
1615 {
1616  checkMethod(tA(), su, "-");
1617  tmp<faMatrix<Type>> tC(tA.ptr());
1618  tC.ref().source() += su.mesh().S()*su.field();
1619  return tC;
1620 }
1621 
1622 
1623 template<class Type>
1624 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1625 (
1626  const tmp<faMatrix<Type>>& tA,
1627  const tmp<DimensionedField<Type, areaMesh>>& tsu
1628 )
1629 {
1630  checkMethod(tA(), tsu(), "-");
1631  tmp<faMatrix<Type>> tC(tA.ptr());
1632  tC.ref().source() += tsu().mesh().S()*tsu().field();
1633  tsu.clear();
1634  return tC;
1635 }
1636 
1637 
1638 template<class Type>
1639 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1640 (
1641  const tmp<faMatrix<Type>>& tA,
1642  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tsu
1643 )
1644 {
1645  checkMethod(tA(), tsu(), "-");
1646  tmp<faMatrix<Type>> tC(tA.ptr());
1647  tC.ref().source() += tsu().mesh().S()*tsu().primitiveField();
1648  tsu.clear();
1649  return tC;
1650 }
1651 
1652 
1653 template<class Type>
1654 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1655 (
1656  const DimensionedField<Type, areaMesh>& su,
1657  const faMatrix<Type>& A
1658 )
1659 {
1660  checkMethod(A, su, "-");
1661  auto tC(A.clone());
1662  tC.ref().negate();
1663  tC.ref().source() -= su.mesh().S()*su.field();
1664  return tC;
1665 }
1666 
1667 
1668 template<class Type>
1669 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1670 (
1671  const tmp<DimensionedField<Type, areaMesh>>& tsu,
1672  const faMatrix<Type>& A
1673 )
1674 {
1675  checkMethod(A, tsu(), "-");
1676  auto tC(A.clone());
1677  tC.ref().negate();
1678  tC.ref().source() -= tsu().mesh().S()*tsu().field();
1679  tsu.clear();
1680  return tC;
1681 }
1682 
1683 
1684 template<class Type>
1685 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1686 (
1687  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tsu,
1688  const faMatrix<Type>& A
1689 )
1690 {
1691  checkMethod(A, tsu(), "-");
1692  auto tC(A.clone());
1693  tC.ref().negate();
1694  tC.ref().source() -= tsu().mesh().S()*tsu().primitiveField();
1695  tsu.clear();
1696  return tC;
1697 }
1698 
1699 
1700 template<class Type>
1701 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1702 (
1703  const DimensionedField<Type, areaMesh>& su,
1704  const tmp<faMatrix<Type>>& tA
1705 )
1706 {
1707  checkMethod(tA(), su, "-");
1708  tmp<faMatrix<Type>> tC(tA.ptr());
1709  tC.ref().negate();
1710  tC.ref().source() -= su.mesh().S()*su.field();
1711  return tC;
1712 }
1713 
1714 
1715 template<class Type>
1716 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1717 (
1718  const tmp<DimensionedField<Type, areaMesh>>& tsu,
1719  const tmp<faMatrix<Type>>& tA
1720 )
1721 {
1722  checkMethod(tA(), tsu(), "-");
1723  tmp<faMatrix<Type>> tC(tA.ptr());
1724  tC.ref().negate();
1725  tC.ref().source() -= tsu().mesh().S()*tsu().field();
1726  tsu.clear();
1727  return tC;
1728 }
1729 
1730 
1731 template<class Type>
1732 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1733 (
1734  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tsu,
1735  const tmp<faMatrix<Type>>& tA
1736 )
1737 {
1738  checkMethod(tA(), tsu(), "-");
1739  tmp<faMatrix<Type>> tC(tA.ptr());
1740  tC.ref().negate();
1741  tC.ref().source() -= tsu().mesh().S()*tsu().primitiveField();
1742  tsu.clear();
1743  return tC;
1744 }
1745 
1746 
1747 template<class Type>
1748 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1749 (
1750  const faMatrix<Type>& A,
1751  const dimensioned<Type>& su
1752 )
1753 {
1754  checkMethod(A, su, "+");
1755  auto tC(A.clone());
1756  tC.ref().source() -= su.value()*A.psi().mesh().S();
1757  return tC;
1758 }
1759 
1760 
1761 template<class Type>
1762 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1763 (
1764  const tmp<faMatrix<Type>>& tA,
1765  const dimensioned<Type>& su
1766 )
1767 {
1768  checkMethod(tA(), su, "+");
1769  tmp<faMatrix<Type>> tC(tA.ptr());
1770  tC.ref().source() -= su.value()*tC().psi().mesh().S();
1771  return tC;
1772 }
1773 
1774 
1775 template<class Type>
1776 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1777 (
1778  const dimensioned<Type>& su,
1779  const faMatrix<Type>& A
1780 )
1781 {
1782  checkMethod(A, su, "+");
1783  auto tC(A.clone());
1784  tC.ref().source() -= su.value()*A.psi().mesh().S();
1785  return tC;
1786 }
1787 
1788 
1789 template<class Type>
1790 Foam::tmp<Foam::faMatrix<Type>> Foam::operator+
1791 (
1792  const dimensioned<Type>& su,
1793  const tmp<faMatrix<Type>>& tA
1794 )
1795 {
1796  checkMethod(tA(), su, "+");
1797  tmp<faMatrix<Type>> tC(tA.ptr());
1798  tC.ref().source() -= su.value()*tC().psi().mesh().S();
1799  return tC;
1800 }
1801 
1802 
1803 template<class Type>
1804 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1805 (
1806  const faMatrix<Type>& A,
1807  const dimensioned<Type>& su
1808 )
1809 {
1810  checkMethod(A, su, "-");
1811  auto tC(A.clone());
1812  tC.ref().source() += su.value()*tC().psi().mesh().S();
1813  return tC;
1814 }
1815 
1816 
1817 template<class Type>
1818 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1819 (
1820  const tmp<faMatrix<Type>>& tA,
1821  const dimensioned<Type>& su
1822 )
1823 {
1824  checkMethod(tA(), su, "-");
1825  tmp<faMatrix<Type>> tC(tA.ptr());
1826  tC.ref().source() += su.value()*tC().psi().mesh().S();
1827  return tC;
1828 }
1829 
1830 
1831 template<class Type>
1832 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1833 (
1834  const dimensioned<Type>& su,
1835  const faMatrix<Type>& A
1836 )
1837 {
1838  checkMethod(A, su, "-");
1839  auto tC(A.clone());
1840  tC.ref().negate();
1841  tC.ref().source() -= su.value()*A.psi().mesh().S();
1842  return tC;
1843 }
1844 
1845 
1846 template<class Type>
1847 Foam::tmp<Foam::faMatrix<Type>> Foam::operator-
1848 (
1849  const dimensioned<Type>& su,
1850  const tmp<faMatrix<Type>>& tA
1851 )
1852 {
1853  checkMethod(tA(), su, "-");
1854  tmp<faMatrix<Type>> tC(tA.ptr());
1855  tC.ref().negate();
1856  tC.ref().source() -= su.value()*tC().psi().mesh().S();
1857  return tC;
1858 }
1859 
1860 
1861 template<class Type>
1862 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1863 (
1864  const faMatrix<Type>& A,
1865  const DimensionedField<Type, areaMesh>& su
1866 )
1867 {
1868  checkMethod(A, su, "==");
1869  auto tC(A.clone());
1870  tC.ref().source() += su.mesh().S()*su.field();
1871  return tC;
1872 }
1873 
1874 
1875 template<class Type>
1876 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1877 (
1878  const faMatrix<Type>& A,
1879  const tmp<DimensionedField<Type, areaMesh>>& tsu
1880 )
1881 {
1882  checkMethod(A, tsu(), "==");
1883  auto tC(A.clone());
1884  tC.ref().source() += tsu().mesh().S()*tsu().field();
1885  tsu.clear();
1886  return tC;
1887 }
1888 
1889 
1890 template<class Type>
1891 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1892 (
1893  const faMatrix<Type>& A,
1894  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tsu
1895 )
1896 {
1897  checkMethod(A, tsu(), "==");
1898  auto tC(A.clone());
1899  tC.ref().source() += tsu().mesh().S()*tsu().primitiveField();
1900  tsu.clear();
1901  return tC;
1902 }
1903 
1904 
1905 template<class Type>
1906 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1907 (
1908  const tmp<faMatrix<Type>>& tA,
1909  const DimensionedField<Type, areaMesh>& su
1910 )
1911 {
1912  checkMethod(tA(), su, "==");
1913  tmp<faMatrix<Type>> tC(tA.ptr());
1914  tC.ref().source() += su.mesh().S()*su.field();
1915  return tC;
1916 }
1917 
1918 
1919 template<class Type>
1920 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1921 (
1922  const tmp<faMatrix<Type>>& tA,
1923  const tmp<DimensionedField<Type, areaMesh>>& tsu
1924 )
1925 {
1926  checkMethod(tA(), tsu(), "==");
1927  tmp<faMatrix<Type>> tC(tA.ptr());
1928  tC.ref().source() += tsu().mesh().S()*tsu().field();
1929  tsu.clear();
1930  return tC;
1931 }
1932 
1933 
1934 template<class Type>
1935 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1936 (
1937  const tmp<faMatrix<Type>>& tA,
1938  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tsu
1939 )
1940 {
1941  checkMethod(tA(), tsu(), "==");
1942  tmp<faMatrix<Type>> tC(tA.ptr());
1943  tC.ref().source() += tsu().mesh().S()*tsu().primitiveField();
1944  tsu.clear();
1945  return tC;
1946 }
1947 
1948 
1949 template<class Type>
1950 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1951 (
1952  const faMatrix<Type>& A,
1953  const dimensioned<Type>& su
1954 )
1955 {
1956  checkMethod(A, su, "==");
1957  auto tC(A.clone());
1958  tC.ref().source() += A.psi().mesh().S()*su.value();
1959  return tC;
1960 }
1961 
1962 
1963 template<class Type>
1964 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1965 (
1966  const tmp<faMatrix<Type>>& tA,
1967  const dimensioned<Type>& su
1968 )
1969 {
1970  checkMethod(tA(), su, "==");
1971  tmp<faMatrix<Type>> tC(tA.ptr());
1972  tC.ref().source() += tC().psi().mesh().S()*su.value();
1973  return tC;
1974 }
1975 
1976 
1977 template<class Type>
1978 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1979 (
1980  const faMatrix<Type>& A,
1981  const Foam::zero
1982 )
1983 {
1984  return A;
1985 }
1986 
1987 
1988 template<class Type>
1989 Foam::tmp<Foam::faMatrix<Type>> Foam::operator==
1990 (
1991  const tmp<faMatrix<Type>>& tA,
1992  const Foam::zero
1993 )
1994 {
1995  return tA;
1996 }
1997 
1998 
1999 template<class Type>
2000 Foam::tmp<Foam::faMatrix<Type>> Foam::operator*
2001 (
2002  const areaScalarField::Internal& dsf,
2003  const faMatrix<Type>& A
2004 )
2005 {
2006  auto tC(A.clone());
2007  tC.ref() *= dsf;
2008  return tC;
2009 }
2010 
2011 
2012 template<class Type>
2013 Foam::tmp<Foam::faMatrix<Type>> Foam::operator*
2014 (
2015  const tmp<areaScalarField::Internal>& tdsf,
2016  const faMatrix<Type>& A
2017 )
2018 {
2019  auto tC(A.clone());
2020  tC.ref() *= tdsf;
2021  return tC;
2022 }
2023 
2024 
2025 template<class Type>
2026 Foam::tmp<Foam::faMatrix<Type>> Foam::operator*
2027 (
2028  const tmp<areaScalarField>& tvsf,
2029  const faMatrix<Type>& A
2030 )
2031 {
2032  auto tC(A.clone());
2033  tC.ref() *= tvsf;
2034  return tC;
2035 }
2036 
2037 
2038 template<class Type>
2039 Foam::tmp<Foam::faMatrix<Type>> Foam::operator*
2040 (
2041  const areaScalarField::Internal& dsf,
2042  const tmp<faMatrix<Type>>& tA
2043 )
2044 {
2045  tmp<faMatrix<Type>> tC(tA.ptr());
2046  tC.ref() *= dsf;
2047  return tC;
2048 }
2049 
2050 
2051 template<class Type>
2052 Foam::tmp<Foam::faMatrix<Type>> Foam::operator*
2053 (
2054  const tmp<areaScalarField::Internal>& tdsf,
2055  const tmp<faMatrix<Type>>& tA
2056 )
2057 {
2058  tmp<faMatrix<Type>> tC(tA.ptr());
2059  tC.ref() *= tdsf;
2060  return tC;
2061 }
2062 
2063 
2064 template<class Type>
2065 Foam::tmp<Foam::faMatrix<Type>> Foam::operator*
2066 (
2067  const tmp<areaScalarField>& tvsf,
2068  const tmp<faMatrix<Type>>& tA
2069 )
2070 {
2071  tmp<faMatrix<Type>> tC(tA.ptr());
2072  tC.ref() *= tvsf;
2073  return tC;
2074 }
2075 
2076 
2077 template<class Type>
2078 Foam::tmp<Foam::faMatrix<Type>> Foam::operator*
2079 (
2080  const dimensioned<scalar>& ds,
2081  const faMatrix<Type>& A
2082 )
2083 {
2084  auto tC(A.clone());
2085  tC.ref() *= ds;
2086  return tC;
2087 }
2088 
2089 
2090 template<class Type>
2091 Foam::tmp<Foam::faMatrix<Type>> Foam::operator*
2092 (
2093  const dimensioned<scalar>& ds,
2094  const tmp<faMatrix<Type>>& tA
2095 )
2096 {
2097  tmp<faMatrix<Type>> tC(tA.ptr());
2098  tC.ref() *= ds;
2099  return tC;
2100 }
2101 
2102 
2103 template<class Type>
2105 Foam::operator&
2106 (
2107  const faMatrix<Type>& M,
2108  const DimensionedField<Type, areaMesh>& psi
2109 )
2110 {
2112  (
2113  "M&" + psi.name(),
2114  psi.mesh(),
2115  M.dimensions()/dimArea,
2117  );
2118  auto& Mphi = tMphi.ref();
2119 
2120  // Loop over field components
2121  if (M.hasDiag())
2122  {
2123  for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
2124  {
2125  scalarField psiCmpt(psi.field().component(cmpt));
2126  scalarField boundaryDiagCmpt(M.diag());
2127  M.addBoundaryDiag(boundaryDiagCmpt, cmpt);
2128  Mphi.primitiveFieldRef().replace(cmpt, -boundaryDiagCmpt*psiCmpt);
2129  }
2130  }
2131  else
2132  {
2133  Mphi.primitiveFieldRef() = Zero;
2134  }
2135 
2136  Mphi.primitiveFieldRef() += M.lduMatrix::H(psi.field()) + M.source();
2137  M.addBoundarySource(Mphi.primitiveFieldRef());
2138 
2139  Mphi.primitiveFieldRef() /= -psi.mesh().S();
2140  Mphi.correctBoundaryConditions();
2141 
2142  return tMphi;
2143 }
2144 
2145 
2146 template<class Type>
2148 Foam::operator&
2149 (
2150  const faMatrix<Type>& M,
2151  const tmp<DimensionedField<Type, areaMesh>>& tpsi
2152 )
2153 {
2154  tmp<GeometricField<Type, faPatchField, areaMesh>> tMpsi = M & tpsi();
2155  tpsi.clear();
2156  return tMpsi;
2157 }
2158 
2159 
2160 template<class Type>
2162 Foam::operator&
2163 (
2164  const faMatrix<Type>& M,
2165  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tpsi
2166 )
2167 {
2168  tmp<GeometricField<Type, faPatchField, areaMesh>> tMpsi = M & tpsi();
2169  tpsi.clear();
2170  return tMpsi;
2171 }
2172 
2173 
2174 template<class Type>
2176 Foam::operator&
2177 (
2178  const tmp<faMatrix<Type>>& tM,
2179  const DimensionedField<Type, areaMesh>& psi
2180 )
2181 {
2182  tmp<GeometricField<Type, faPatchField, areaMesh>> tMpsi = tM() & psi;
2183  tM.clear();
2184  return tMpsi;
2185 }
2186 
2187 
2188 template<class Type>
2190 Foam::operator&
2191 (
2192  const tmp<faMatrix<Type>>& tM,
2193  const tmp<DimensionedField<Type, areaMesh>>& tpsi
2194 )
2195 {
2196  tmp<GeometricField<Type, faPatchField, areaMesh>> tMpsi = tM() & tpsi();
2197  tM.clear();
2198  tpsi.clear();
2199  return tMpsi;
2200 }
2201 
2202 
2203 template<class Type>
2205 Foam::operator&
2206 (
2207  const tmp<faMatrix<Type>>& tM,
2208  const tmp<GeometricField<Type, faPatchField, areaMesh>>& tpsi
2209 )
2210 {
2211  tmp<GeometricField<Type, faPatchField, areaMesh>> tMpsi = tM() & tpsi();
2212  tM.clear();
2213  tpsi.clear();
2214  return tMpsi;
2215 }
2216 
2217 
2218 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
2219 
2220 template<class Type>
2221 Foam::Ostream& Foam::operator<<(Ostream& os, const faMatrix<Type>& fam)
2222 {
2223  os << static_cast<const lduMatrix&>(fam) << nl
2224  << fam.dimensions_ << nl
2225  << fam.source_ << nl
2226  << fam.internalCoeffs_ << nl
2227  << fam.boundaryCoeffs_ << endl;
2228 
2230 
2231  return os;
2232 }
2233 
2234 
2235 // * * * * * * * * * * * * * * * * Solvers * * * * * * * * * * * * * * * * * //
2236 
2237 #include "faMatrixSolve.C"
2238 
2239 // ************************************************************************* //
void negate()
Inplace negate.
Definition: faMatrix.C:803
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition: faMesh.H:87
faceListList boundary
void setValues(const labelUList &faceLabels, const Type &value)
Set solution in given faces to the specified value and eliminate the corresponding equations from the...
Definition: faMatrix.C:402
void operator-=(const faMatrix< Type > &)
Definition: faMatrix.C:852
tmp< Field< Type > > faceH(const Field< Type > &) const
tmp< scalarField > D() const
Return the matrix diagonal.
Definition: faMatrix.C:606
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
uint8_t direction
Definition: direction.H:46
label faceId(-1)
tmp< DimensionedField< typename DimensionedField< Type, GeoMesh >::cmptType, GeoMesh >> cmptAv(const DimensionedField< Type, GeoMesh > &f1)
void operator+=(const faMatrix< Type > &)
Definition: faMatrix.C:818
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
const dictionary & solverDict() const
Return the solver dictionary for psi.
Definition: faMatrix.C:750
UEqn relax()
faMatrix(const GeometricField< Type, faPatchField, areaMesh > &psi, const dimensionSet &ds)
Construct given a field to solve for.
Definition: faMatrix.C:179
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
const labelListList & faceEdges() const
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:45
void addToInternalField(const labelUList &addr, const Field< Type2 > &pf, Field< Type2 > &intf) const
Add patch contribution to internal field.
Definition: faMatrix.C:36
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: tmpI.H:235
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
void addBoundaryDiag(scalarField &diag, const direction cmpt) const
Definition: faMatrix.C:111
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static const word & extrapolatedCalculatedType() noexcept
The type name for extrapolatedCalculated patch fields combines zero-gradient and calculated.
Definition: faPatchField.H:183
void setReferences(const labelUList &faceLabels, const Type &value, const bool forceReference=false)
Set reference level for solution.
Definition: faMatrix.C:454
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
Definition: stringOps.C:1187
Generic GeometricField class.
Definition: areaFieldsFwd.H:50
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept
The number of components associated with given valueTypeCode.
Definition: exprTraits.C:40
Generic dimensioned Type class.
labelList faceLabels(nFaceLabels)
DimensionedField< scalar, areaMesh > Internal
The internal field type from which this GeometricField is derived.
void addBoundarySource(Field< Type > &source, const bool couples=true) const
Definition: faMatrix.C:145
conserve primitiveFieldRef()+
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
const labelUList & neighbour() const
Internal face neighbour.
Definition: fvMesh.H:580
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
tmp< GeometricField< Type, faePatchField, edgeMesh > > flux() const
Return the face-flux field from the matrix.
Definition: faMatrix.C:670
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:164
Dimension set for the base types, which can be used to implement rigorous dimension checking for alge...
Definition: dimensionSet.H:105
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
void subtractFromInternalField(const labelUList &addr, const Field< Type2 > &pf, Field< Type2 > &intf) const
Subtract patch contribution from internal field.
Definition: faMatrix.C:74
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
void relax()
Relax matrix (for steady-state solution).
Definition: faMatrix.C:589
void operator=(const faMatrix< Type > &)
Definition: faMatrix.C:762
Generic templated field type.
Definition: Field.H:62
A class for handling words, derived from Foam::string.
Definition: word.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
SolverPerformance is the class returned by the LduMatrix solver containing performance statistics...
#define DebugInFunction
Report an information message using Foam::Info.
void checkMethod(const faMatrix< Type > &, const faMatrix< Type > &, const char *)
Definition: faMatrix.C:1043
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition: tmp.H:206
tmp< GeometricField< Type, faPatchField, areaMesh > > H() const
Return the H operation source.
Definition: faMatrix.C:634
errorManip< error > abort(error &err)
Definition: errorManip.H:139
void setValuesFromList(const labelUList &faceLabels, const ListType< Type > &values)
Set solution in given faces to the specified values.
Definition: faMatrix.C:299
void operator=(const lduMatrix &)
SolverPerformance< Type > solve(faMatrix< Type > &, const dictionary &solverControls)
Solve returning the solution statistics given convergence tolerance.
static tmp< GeometricField< scalar, faPatchField, areaMesh > > New(const word &name, IOobjectOption::registerOption regOpt, const Mesh &mesh, const dimensionSet &dims, const word &patchFieldType=faPatchField< scalar >::calculatedType())
Return tmp field (NO_READ, NO_WRITE) from name, mesh, dimensions and patch type. [Takes current timeN...
dimensioned< Type > cmptMultiply(const dimensioned< Type > &, const dimensioned< Type > &)
void cmptMag(FieldField< Field, Type > &cf, const FieldField< Field, Type > &f)
const Mesh & mesh() const noexcept
Return mesh.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
void operator*=(const scalarField &)
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
tmp< areaScalarField > A() const
Return the central coefficient.
Definition: faMatrix.C:615
const labelUList & owner() const
Internal face owner. Note bypassing virtual mechanism so.
Definition: fvMesh.H:572
void setReference(const label facei, const Type &value, const bool forceReference=false)
Set reference level for solution.
Definition: faMatrix.C:435
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
const Field< Type > & field() const noexcept
Return const-reference to the field values.
Template functions to aid in the implementation of demand driven data.
lduMatrix is a general matrix class in which the coefficients are stored as three arrays...
Definition: lduMatrix.H:79
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field values.
Finite-Area matrix basic solvers.
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Definition: stringOps.C:1171
static bool checking() noexcept
True if dimension checking is enabled (the usual default)
Definition: dimensionSet.H:241
A List with indirect addressing. Like IndirectList but does not store addressing. ...
Definition: faMatrix.H:56
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: areaFieldsFwd.H:42
A single value that is represented as a list with an operator[] to access the value. This can be useful for templated operations expecting a list accessor.
Definition: UniformList.H:48
A special matrix type and solver, designed for finite area solutions of scalar equations. Face addressing is used to make all matrix assembly and solution loops vectorise.
Definition: faMatricesFwd.H:37
void correctBoundaryConditions()
Correct boundary field.
const fvBoundaryMesh & boundary() const noexcept
Return reference to boundary mesh.
Definition: fvMesh.H:395
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
const GeometricField< Type, faPatchField, areaMesh > & psi() const
Definition: faMatrix.H:352
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition: tmpI.H:289
const volScalarField & psi
tmp< Field< Type > > H(const Field< Type > &) const
const dimensionedScalar & D
void operator-=(const lduMatrix &)
void addCmptAvBoundaryDiag(scalarField &diag) const
Definition: faMatrix.C:129
void operator+=(const lduMatrix &)
T * ptr() const
Return managed pointer for reuse, or clone() the object reference.
Definition: tmpI.H:256
A class for managing temporary objects.
Definition: HashPtrTable.H:50
void cmptMin(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
static const Foam::dimensionedScalar A("", Foam::dimPressure, 611.21)
void deleteDemandDrivenData(DataPtr &dataPtr)
Calculate the matrix for the second temporal derivative.
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
#define M(I)
static const Foam::dimensionedScalar B("", Foam::dimless, 18.678)
const dimensionSet dimArea(sqr(dimLength))
Definition: dimensionSets.H:57
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
virtual ~faMatrix()
Destructor.
Definition: faMatrix.C:285