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