fvMatrix.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) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2016-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 "volFields.H"
30 #include "surfaceFields.H"
33 #include "coupledFvPatchFields.H"
34 #include "IndirectList.H"
35 #include "UniformList.H"
36 #include "demandDrivenData.H"
37 
38 #include "cyclicFvPatchField.H"
39 #include "cyclicAMIFvPatchField.H"
40 #include "cyclicACMIFvPatchField.H"
41 
43 
44 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
45 
46 template<class Type>
47 template<class Type2>
49 (
50  const labelUList& addr,
51  const Field<Type2>& pf,
52  Field<Type2>& intf
53 ) const
54 {
55  if (addr.size() != pf.size())
56  {
58  << "addressing (" << addr.size()
59  << ") and field (" << pf.size() << ") are different sizes" << endl
60  << abort(FatalError);
61  }
62 
63  forAll(addr, facei)
64  {
65  intf[addr[facei]] += pf[facei];
66  }
67 }
68 
69 
70 template<class Type>
71 template<class Type2>
73 (
74  const labelUList& addr,
75  const tmp<Field<Type2>>& tpf,
76  Field<Type2>& intf
77 ) const
78 {
79  addToInternalField(addr, tpf(), intf);
80  tpf.clear();
81 }
82 
83 
84 template<class Type>
85 template<class Type2>
87 (
88  const labelUList& addr,
89  const Field<Type2>& pf,
90  Field<Type2>& intf
91 ) const
92 {
93  if (addr.size() != pf.size())
94  {
96  << "addressing (" << addr.size()
97  << ") and field (" << pf.size() << ") are different sizes" << endl
98  << abort(FatalError);
99  }
100 
101  forAll(addr, facei)
102  {
103  intf[addr[facei]] -= pf[facei];
104  }
105 }
106 
107 
108 template<class Type>
109 template<class Type2>
111 (
112  const labelUList& addr,
113  const tmp<Field<Type2>>& tpf,
114  Field<Type2>& intf
115 ) const
116 {
117  subtractFromInternalField(addr, tpf(), intf);
118  tpf.clear();
119 }
120 
121 
122 template<class Type>
124 (
125  scalarField& diag,
126  const direction solveCmpt
127 ) const
128 {
129  for (label fieldi = 0; fieldi < nMatrices(); ++fieldi)
130  {
131  const auto& bpsi = this->psi(fieldi).boundaryField();
132 
133  forAll(bpsi, ptfi)
134  {
135  const label patchi = globalPatchID(fieldi, ptfi);
136 
137  if (patchi != -1)
138  {
139  addToInternalField
140  (
141  lduAddr().patchAddr(patchi),
142  internalCoeffs_[patchi].component(solveCmpt),
143  diag
144  );
145  }
146  }
147  }
148 }
149 
150 
151 template<class Type>
153 {
154  for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
155  {
156  const auto& bpsi = this->psi(fieldi).boundaryField();
157 
158  forAll(bpsi, ptfi)
159  {
160  const label patchi = globalPatchID(fieldi, ptfi);
161  if (patchi != -1)
162  {
163  addToInternalField
164  (
165  lduAddr().patchAddr(patchi),
166  cmptAv(internalCoeffs_[patchi]),
167  diag
168  );
169  }
170  }
171  }
172 }
173 
174 
175 template<class Type>
177 (
178  Field<Type>& source,
179  const bool couples
180 ) const
181 {
182  for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
183  {
184  const auto& bpsi = this->psi(fieldi).boundaryField();
185 
186  forAll(bpsi, ptfi)
187  {
188  const fvPatchField<Type>& ptf = bpsi[ptfi];
189 
190  const label patchi = globalPatchID(fieldi, ptfi);
191 
192  if (patchi != -1)
193  {
194  const Field<Type>& pbc = boundaryCoeffs_[patchi];
195 
196  if (!ptf.coupled())
197  {
198  addToInternalField
199  (
200  lduAddr().patchAddr(patchi),
201  pbc,
202  source
203  );
204  }
205  else if (couples)
206  {
207  const tmp<Field<Type>> tpnf = ptf.patchNeighbourField();
208  const Field<Type>& pnf = tpnf();
209 
210  const labelUList& addr = lduAddr().patchAddr(patchi);
211 
212  forAll(addr, facei)
213  {
214  source[addr[facei]] +=
215  cmptMultiply(pbc[facei], pnf[facei]);
216  }
217  }
218  }
219  }
220  }
221 }
222 
223 
224 template<class Type>
225 template<template<class> class ListType>
227 (
228  const labelUList& cellLabels,
229  const ListType<Type>& values
230 )
231 {
232  const fvMesh& mesh = psi_.mesh();
233 
234  const cellList& cells = mesh.cells();
235  const labelUList& own = mesh.owner();
236  const labelUList& nei = mesh.neighbour();
237 
238  scalarField& Diag = diag();
239  Field<Type>& psi =
240  const_cast
241  <
242  GeometricField<Type, fvPatchField, volMesh>&
243  >(psi_).primitiveFieldRef();
244 
245 
246  // Following actions:
247  // - adjust local field psi
248  // - set local matrix to be diagonal (so adjust source)
249  // - cut connections to neighbours
250  // - make (on non-adjusted cells) contribution explicit
251 
252  if (symmetric() || asymmetric())
253  {
254  forAll(cellLabels, i)
255  {
256  const label celli = cellLabels[i];
257  const Type& value = values[i];
258 
259  for (const label facei : cells[celli])
260  {
261  if (mesh.isInternalFace(facei))
262  {
263  if (symmetric())
264  {
265  if (celli == own[facei])
266  {
267  source_[nei[facei]] -= upper()[facei]*value;
268  }
269  else
270  {
271  source_[own[facei]] -= upper()[facei]*value;
272  }
273 
274  upper()[facei] = 0.0;
275  }
276  else
277  {
278  if (celli == own[facei])
279  {
280  source_[nei[facei]] -= lower()[facei]*value;
281  }
282  else
283  {
284  source_[own[facei]] -= upper()[facei]*value;
285  }
286 
287  upper()[facei] = 0.0;
288  lower()[facei] = 0.0;
289  }
290  }
291  else
292  {
293  const label patchi = mesh.boundaryMesh().whichPatch(facei);
294 
295  if (internalCoeffs_[patchi].size())
296  {
297  const label patchFacei =
298  mesh.boundaryMesh()[patchi].whichFace(facei);
299 
300  internalCoeffs_[patchi][patchFacei] = Zero;
301  boundaryCoeffs_[patchi][patchFacei] = Zero;
302  }
303  }
304  }
305  }
306  }
307 
308  // Note: above loop might have affected source terms on adjusted cells
309  // so make sure to adjust them afterwards
310  forAll(cellLabels, i)
311  {
312  const label celli = cellLabels[i];
313  const Type& value = values[i];
314 
315  psi[celli] = value;
316  source_[celli] = value*Diag[celli];
317  }
318 }
319 
320 
321 template<class Type>
322 bool Foam::fvMatrix<Type>::checkImplicit(const label fieldi)
323 {
324  const auto& bpsi = this->psi(fieldi).boundaryField();
325 
326  word idName;
327  forAll(bpsi, patchi)
328  {
329  if (bpsi[patchi].useImplicit())
330  {
331  if (debug)
332  {
333  Pout<< "fvMatrix<Type>::checkImplicit "
334  << " field:" << this->psi(fieldi).name()
335  << " on mesh:"
336  << this->psi(fieldi).mesh().name()
337  << " patch:" << bpsi[patchi].patch().name()
338  << endl;
339  }
340 
341  idName += Foam::name(patchi);
342  useImplicit_ = true;
343  }
344  }
345 
346  if (useImplicit_)
347  {
348  lduAssemblyName_ = word("lduAssembly") + idName;
349  }
350 
351  return !idName.empty();
352 }
353 
354 
355 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
356 
357 template<class Type>
359 (
361  const dimensionSet& ds
362 )
363 :
364  lduMatrix(psi.mesh()),
365  psi_(psi),
366  useImplicit_(false),
367  lduAssemblyName_(),
368  nMatrix_(0),
369  dimensions_(ds),
370  source_(psi.size(), Zero),
371  internalCoeffs_(psi.mesh().boundary().size()),
372  boundaryCoeffs_(psi.mesh().boundary().size()),
373  faceFluxCorrectionPtr_(nullptr)
374 {
376  << "Constructing fvMatrix<Type> for field " << psi_.name() << endl;
377 
378  checkImplicit();
379 
380  forAll(psi.mesh().boundary(), patchi)
381  {
382  internalCoeffs_.set
383  (
384  patchi,
385  new Field<Type>(psi.mesh().boundary()[patchi].size(), Zero)
386  );
387 
388  boundaryCoeffs_.set
389  (
390  patchi,
391  new Field<Type>(psi.mesh().boundary()[patchi].size(), Zero)
392  );
393  }
394 
395  auto& psiRef = this->psi(0);
396  const label currentStatePsi = psiRef.eventNo();
397  psiRef.boundaryFieldRef().updateCoeffs();
398  psiRef.eventNo() = currentStatePsi;
399 }
400 
401 
402 template<class Type>
404 :
405  lduMatrix(fvm),
406  psi_(fvm.psi_),
407  useImplicit_(fvm.useImplicit_),
408  lduAssemblyName_(fvm.lduAssemblyName_),
409  nMatrix_(fvm.nMatrix_),
410  dimensions_(fvm.dimensions_),
411  source_(fvm.source_),
412  internalCoeffs_(fvm.internalCoeffs_),
413  boundaryCoeffs_(fvm.boundaryCoeffs_),
414  faceFluxCorrectionPtr_(nullptr)
415 {
417  << "Copying fvMatrix<Type> for field " << psi_.name() << endl;
418 
419  if (fvm.faceFluxCorrectionPtr_)
420  {
421  faceFluxCorrectionPtr_ =
423  (
424  *(fvm.faceFluxCorrectionPtr_)
425  );
426  }
427 }
428 
429 
430 template<class Type>
431 Foam::fvMatrix<Type>::fvMatrix(const tmp<fvMatrix<Type>>& tmat)
432 :
433  lduMatrix(tmat.constCast(), tmat.movable()),
434  psi_(tmat().psi_),
435  useImplicit_(tmat().useImplicit_),
436  lduAssemblyName_(tmat().lduAssemblyName_),
437  nMatrix_(tmat().nMatrix_),
438  dimensions_(tmat().dimensions_),
439  source_(tmat.constCast().source_, tmat.movable()),
440  internalCoeffs_(tmat.constCast().internalCoeffs_, tmat.movable()),
441  boundaryCoeffs_(tmat.constCast().boundaryCoeffs_, tmat.movable()),
442  faceFluxCorrectionPtr_(nullptr)
443 {
445  << "Copy/move fvMatrix<Type> for field " << psi_.name() << endl;
446 
447  if (tmat().faceFluxCorrectionPtr_)
448  {
449  if (tmat.movable())
450  {
451  faceFluxCorrectionPtr_ = tmat().faceFluxCorrectionPtr_;
452  tmat().faceFluxCorrectionPtr_ = nullptr;
453  }
454  else
455  {
456  faceFluxCorrectionPtr_ =
457  new GeometricField<Type, fvsPatchField, surfaceMesh>
458  (
459  *(tmat().faceFluxCorrectionPtr_)
460  );
461  }
462  }
463 
464  tmat.clear();
465 }
466 
467 
468 // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * * //
469 
470 template<class Type>
472 {
474  << "Destroying fvMatrix<Type> for field " << psi_.name() << endl;
475 
476  deleteDemandDrivenData(faceFluxCorrectionPtr_);
477  subMatrices_.clear();
478 }
479 
480 
481 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
482 
483 template<class Type>
485 (
486  lduInterfaceFieldPtrsList& interfaces,
487  PtrDynList<lduInterfaceField>& newInterfaces
488 )
489 {
490  interfaces.setSize(internalCoeffs_.size());
491  for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
492  {
493  const auto& bpsi = this->psi(fieldi).boundaryField();
494  lduInterfaceFieldPtrsList fieldInterfaces(bpsi.scalarInterfaces());
495 
496  forAll (fieldInterfaces, patchi)
497  {
498  label globalPatchID = lduMeshPtr()->patchMap()[fieldi][patchi];
499 
500  if (globalPatchID != -1)
501  {
502  if (fieldInterfaces.set(patchi))
503  {
504  if (isA<cyclicLduInterfaceField>(bpsi[patchi]))
505  {
506  newInterfaces.append
507  (
509  (
510  refCast<const fvPatch>
511  (
512  lduMeshPtr()->interfaces()[globalPatchID]
513  ),
514  bpsi[patchi].internalField()
515  )
516  );
517  interfaces.set(globalPatchID, &newInterfaces.last());
518 
519  }
520  else if (isA<cyclicAMILduInterfaceField>(bpsi[patchi]))
521  {
522  newInterfaces.append
523  (
525  (
526  refCast<const fvPatch>
527  (
528  lduMeshPtr()->interfaces()[globalPatchID]
529  ),
530  bpsi[patchi].internalField()
531  )
532  );
533  interfaces.set(globalPatchID, &newInterfaces.last());
534  }
535  else if (isA<cyclicACMILduInterfaceField>(bpsi[patchi]))
536  {
537  newInterfaces.append
538  (
540  (
541  refCast<const fvPatch>
542  (
543  lduMeshPtr()->interfaces()[globalPatchID]
544  ),
545  bpsi[patchi].internalField()
546  )
547  );
548  interfaces.set(globalPatchID, &newInterfaces.last());
549  }
550  else
551  {
552  interfaces.set(globalPatchID, &fieldInterfaces[patchi]);
553  }
554  }
555  }
556  }
557  }
558 }
559 
560 
561 template<class Type>
563 (
564  label fieldi,
565  const FieldField<Field, Type>& fluxContrib,
566  FieldField<Field, Type>& contrib,
567  bool internal
568 ) const
569 {
570  const lduPrimitiveMeshAssembly* ptr = lduMeshPtr();
571 
572  const labelList& patchMap = ptr->patchMap()[fieldi];
573 
574  forAll(contrib, patchi)
575  {
576  const label globalPtchId = patchMap[patchi];
577 
578  if (globalPtchId != -1)
579  {
580  // Cache contrib before overwriting
581  const Field<Type> saveContrib(fluxContrib[globalPtchId]);
582  contrib[patchi].setSize(psi_.boundaryField()[patchi].size()),
583  contrib[patchi] = pTraits<Type>::zero;
584 
585  if (internal)
586  {
587  contrib[patchi] =
589  (
590  saveContrib,
591  psi_.boundaryField()[patchi].patchInternalField()
592  );
593  }
594  else
595  {
596  if (this->psi(fieldi).boundaryField()[patchi].coupled())
597  {
598  contrib[patchi] =
600  (
601  saveContrib,
602  psi_.boundaryField()[patchi].patchNeighbourField()
603  );
604  }
605  }
606  }
607  else if (globalPtchId == -1)
608  {
609  const polyPatch& pp =
610  this->psi(fieldi).mesh().boundaryMesh()[patchi];
611 
612  if (pp.masterImplicit())
613  {
614  label virtualPatch =
615  ptr->patchLocalToGlobalMap()[fieldi][patchi];
616 
617  const label nbrPatchId = pp.neighbPolyPatchID();
618 
619  // Copy contrib before overwriting
620  const Field<Type> saveContrib(fluxContrib[virtualPatch]);
621 
622  Field<Type>& coeffs = contrib[patchi];
623  Field<Type>& nbrCoeffs = contrib[nbrPatchId];
624 
625  coeffs.setSize(psi_.boundaryField()[patchi].size());
626  nbrCoeffs.setSize(psi_.boundaryField()[nbrPatchId].size());
627 
628  coeffs = pTraits<Type>::zero;
629  nbrCoeffs = pTraits<Type>::zero;
630 
631  // nrb cells
632  const labelList& nbrCellIds =
633  ptr->cellBoundMap()[fieldi][patchi];
634 
635  const labelList& cellIds =
636  ptr->cellBoundMap()[fieldi][nbrPatchId];
637 
638  const GeometricField<Type, fvPatchField, volMesh>& psi =
639  this->psi(fieldi);
640 
641  forAll(saveContrib, subFaceI)
642  {
643  const label faceId =
644  ptr->facePatchFaceMap()[fieldi][patchi][subFaceI];
645  const label nbrFaceId =
646  ptr->facePatchFaceMap()[fieldi][nbrPatchId][subFaceI];
647 
648  const label nbrCellId = nbrCellIds[subFaceI];
649  const label cellId = cellIds[subFaceI];
650 
651  if (internal)
652  {
653  coeffs[faceId] +=
654  cmptMultiply(saveContrib[subFaceI], psi[cellId]);
655 
656  nbrCoeffs[nbrFaceId] +=
657  cmptMultiply(saveContrib[subFaceI], psi[nbrCellId]);
658  }
659  else //boundary
660  {
661  coeffs[faceId] +=
662  cmptMultiply(saveContrib[subFaceI], psi[nbrCellId]);
663 
664  nbrCoeffs[nbrFaceId] +=
665  cmptMultiply(saveContrib[subFaceI], psi[cellId]);
666  }
667  }
668  }
669  }
670  }
671 }
672 
673 
674 template<class Type>
676 {
677  // If it is a multi-fvMatrix needs correct internalCoeffs and
678  // boundaryCoeffs size
679  if (nMatrix_ > 0)
680  {
681  label interfaceI(0);
682  for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
683  {
684  const auto& psi = this->psi(fieldi);
685 
686  forAll(psi.mesh().boundary(), patchi)
687  {
688  interfaceI++;
689  }
690  }
691  internalCoeffs_.setSize(interfaceI);
692  boundaryCoeffs_.setSize(interfaceI);
693 
694  interfaceI = 0;
695  for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
696  {
697  const auto& psi = this->psi(fieldi);
698 
699  forAll(psi.mesh().boundary(), patchi)
700  {
701  internalCoeffs_.set
702  (
703  interfaceI,
704  new Field<Type>(psi.mesh().boundary()[patchi].size(), Zero)
705  );
706 
707  boundaryCoeffs_.set
708  (
709  interfaceI,
710  new Field<Type>(psi.mesh().boundary()[patchi].size(), Zero)
711  );
712  interfaceI++;
713  }
714  }
715  }
716 
717  for (label i=0; i < nMatrices(); ++i)
718  {
719  const auto& bpsi = this->psi(i).boundaryField();
720 
721  // Cache to-be implicit internal/boundary
722  FieldField<Field, Type> boundary(bpsi.size());
723  FieldField<Field, Type> internal(bpsi.size());
724 
725  label implicit = 0;
726  forAll(bpsi, patchI)
727  {
728  label globalPatchId = lduMeshPtr()->patchMap()[i][patchI];
729  if (globalPatchId == -1)
730  {
731  boundary.set
732  (
733  implicit,
734  matrix(i).boundaryCoeffs()[patchI].clone()
735  );
736  internal.set
737  (
738  implicit,
739  matrix(i).internalCoeffs()[patchI].clone()
740  );
741  implicit++;
742  }
743  }
744 
745  // Update non-implicit patches (re-order)
746  forAll(bpsi, patchI)
747  {
748  label globalPatchId = lduMeshPtr()->patchMap()[i][patchI];
749  if (globalPatchId != -1)
750  {
751  if (matrix(i).internalCoeffs().set(patchI))
752  {
753  internalCoeffs_.set
754  (
755  globalPatchId,
756  matrix(i).internalCoeffs()[patchI].clone()
757  );
758  }
759 
760  if (matrix(i).boundaryCoeffs().set(patchI))
761  {
762  boundaryCoeffs_.set
763  (
764  globalPatchId,
765  matrix(i).boundaryCoeffs()[patchI].clone()
766  );
767  }
768  }
769  }
770 
771  // Store implicit patches at the end of the list
772  implicit = 0;
773  forAll(bpsi, patchI)
774  {
775  label globalPatchId = lduMeshPtr()->patchMap()[i][patchI];
776  if (globalPatchId == -1)
777  {
778  const label implicitPatchId =
779  lduMeshPtr()->patchLocalToGlobalMap()[i][patchI];
780 
781  internalCoeffs_.set
782  (
783  implicitPatchId, internal[implicit].clone()
784  );
785  boundaryCoeffs_.set
786  (
787  implicitPatchId, boundary[implicit].clone()
788  );
789 
790  implicit++;
791  }
792  }
793  }
794 
795 // forAll(internalCoeffs_, patchI)
796 // {
797 // DebugVar(patchI)
798 // DebugVar(internalCoeffs_[patchI])
799 // DebugVar(boundaryCoeffs_[patchI])
800 // }
801 }
802 
803 
804 template<class Type>
806 {
807  for (label i=0; i < nMatrices(); ++i)
808  {
809  forAll(psi(i).boundaryField(), patchI)
810  {
811  label globalPatchId = lduMeshPtr()->patchMap()[i][patchI];
812 
813  if (globalPatchId == -1)
814  {
815  psi(i).boundaryFieldRef()[patchI].manipulateMatrix
816  (
817  *this,
818  i,
819  cmp
820  );
821  }
822  }
823  }
824 }
825 
826 
827 template<class Type>
829 {
830  const labelListList& faceMap = lduMeshPtr()->faceMap();
831  const labelList& cellMap = lduMeshPtr()->cellOffsets();
832 
833  label newFaces = lduMeshPtr()->lduAddr().upperAddr().size();
834  label newCells = lduMeshPtr()->lduAddr().size();
835 
836  scalarField lowerAssemb(newFaces, Zero);
837  scalarField upperAssemb(newFaces, Zero);
838  scalarField diagAssemb(newCells, Zero);
839  Field<Type> sourceAssemb(newCells, Zero);
840 
841  bool asymmetricAssemby = false;
842  for (label i=0; i < nMatrices(); ++i)
843  {
844  if (matrix(i).asymmetric())
845  {
846  asymmetricAssemby = true;
847  }
848  }
849  // Move append contents into intermediate list
850  for (label i=0; i < nMatrices(); ++i)
851  {
852  if (asymmetricAssemby)
853  {
854  const scalarField lowerSub(matrix(i).lower());
855  forAll(lowerSub, facei)
856  {
857  lowerAssemb[faceMap[i][facei]] = lowerSub[facei];
858  }
859  }
860 
861  const scalarField upperSub(matrix(i).upper());
862  const scalarField diagSub(matrix(i).diag());
863  const Field<Type> sourceSub(matrix(i).source());
864 
865  forAll(upperSub, facei)
866  {
867  upperAssemb[faceMap[i][facei]] = upperSub[facei];
868  }
869 
870  forAll(diagSub, celli)
871  {
872  const label globalCelli = cellMap[i] + celli;
873  diagAssemb[globalCelli] = diagSub[celli];
874  sourceAssemb[globalCelli] = sourceSub[celli];
875  }
876  }
877 
878  if (asymmetricAssemby)
879  {
880  lower().setSize(newFaces, Zero);
881  lower() = lowerAssemb;
882  }
883  upper().setSize(newFaces, Zero);
884  upper() = upperAssemb;
885 
886  diag().setSize(newCells, Zero);
887  diag() = diagAssemb;
889  source().setSize(newCells, Zero);
890  source() = sourceAssemb;
891 }
892 
893 
894 template<class Type>
896 {
897  const lduPrimitiveMeshAssembly* lduAssemMeshPtr =
898  psi_.mesh().thisDb().objectRegistry::template findObject
899  <
901  > (lduAssemblyName_);
902 
903  return const_cast<lduPrimitiveMeshAssembly*>(lduAssemMeshPtr);
904 }
905 
906 
907 template<class Type>
909 {
910  return
911  (
912  psi_.mesh().thisDb().objectRegistry::template cfindObject
913  <
915  > (lduAssemblyName_)
916  );
917 }
918 
919 
920 template<class Type>
922 {
923  lduPrimitiveMeshAssembly* ptr = lduMeshPtr();
924 
925  IOobject io
926  (
927  lduAssemblyName_,
928  psi_.mesh().time().timeName(),
929  psi_.mesh().thisDb(),
933  );
934 
935  UPtrList<lduMesh> uMeshPtr(nMatrices());
936 
938  uFieldPtr(nMatrices());
939 
940  for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
941  {
942  const fvMesh& meshi = this->psi(fieldi).mesh();
943  uMeshPtr.set
944  (
945  fieldi,
946  &const_cast<fvMesh&>(meshi)
947  );
948  uFieldPtr.set(fieldi, &this->psi(fieldi));
949  }
950 
951  if (!ptr)
952  {
953  lduPrimitiveMeshAssembly* lduAssemMeshPtr =
954  new lduPrimitiveMeshAssembly(io, uMeshPtr);
955 
956  lduAssemMeshPtr->store();
957  lduAssemMeshPtr->update(uFieldPtr);
958 
959  Info
960  << "Creating lduPrimitiveAssembly: " << lduAssemblyName_ << endl;
961  }
962  else if
963  (
964  psi_.mesh().changing() && !psi_.mesh().upToDatePoints(*ptr)
965  )
966  {
967  // Clear losortPtr_, ownerStartPtr_, losortStartPtr_
968  ptr->lduAddr().clearOut();
969  ptr->update(uFieldPtr);
970  psi_.mesh().setUpToDatePoints(*ptr);
971 
972  Info
973  << "Updating lduPrimitiveAssembly: " << lduAssemblyName_ << endl;
974  }
975  else
976  {
977  Info
978  << "Using lduPrimitiveAssembly: " << lduAssemblyName_ << endl;
979  }
980 }
981 
982 
983 template<class Type>
985 (
986  const labelUList& cellLabels,
987  const Type& value
988 )
989 {
990  this->setValuesFromList(cellLabels, UniformList<Type>(value));
991 }
992 
993 
994 template<class Type>
996 (
997  const labelUList& cellLabels,
998  const UList<Type>& values
999 )
1001  this->setValuesFromList(cellLabels, values);
1002 }
1003 
1004 
1005 template<class Type>
1007 (
1008  const labelUList& cellLabels,
1010 )
1012  this->setValuesFromList(cellLabels, values);
1013 }
1014 
1015 
1016 template<class Type>
1018 (
1019  const label celli,
1020  const Type& value,
1021  const bool forceReference
1022 )
1023 {
1024  if ((forceReference || psi_.needReference()) && celli >= 0)
1025  {
1026  source()[celli] += diag()[celli]*value;
1027  diag()[celli] += diag()[celli];
1028  }
1029 }
1030 
1031 
1032 template<class Type>
1034 (
1035  const labelUList& cellLabels,
1036  const Type& value,
1037  const bool forceReference
1038 )
1039 {
1040  if (forceReference || psi_.needReference())
1041  {
1042  forAll(cellLabels, celli)
1043  {
1044  const label cellId = cellLabels[celli];
1045  if (cellId >= 0)
1046  {
1047  source()[cellId] += diag()[cellId]*value;
1048  diag()[cellId] += diag()[cellId];
1049  }
1050  }
1051  }
1052 }
1053 
1054 
1055 template<class Type>
1057 (
1058  const labelUList& cellLabels,
1059  const UList<Type>& values,
1060  const bool forceReference
1061 )
1062 {
1063  if (forceReference || psi_.needReference())
1064  {
1065  forAll(cellLabels, celli)
1066  {
1067  const label cellId = cellLabels[celli];
1068  if (cellId >= 0)
1069  {
1070  source()[cellId] += diag()[cellId]*values[celli];
1071  diag()[cellId] += diag()[cellId];
1072  }
1073  }
1074  }
1075 }
1076 
1077 
1078 template<class Type>
1079 void Foam::fvMatrix<Type>::addFvMatrix(fvMatrix& matrix)
1080 {
1081  subMatrices_.append(matrix.clone());
1082  ++nMatrix_;
1083 
1084  if (dimensions_ != matrix.dimensions())
1085  {
1087  << "incompatible dimensions for matrix addition "
1088  << endl << " "
1089  << "[" << dimensions_ << " ] "
1090  << " [" << matrix.dimensions() << " ]"
1091  << abort(FatalError);
1092  }
1093 
1094  for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
1095  {
1096  if (checkImplicit(fieldi))
1097  {
1098  break;
1099  }
1100  }
1102  internalCoeffs_.clear();
1103  boundaryCoeffs_.clear();
1104 }
1105 
1106 
1107 template<class Type>
1108 void Foam::fvMatrix<Type>::relax(const scalar alpha)
1109 {
1110  if (alpha <= 0)
1111  {
1112  return;
1113  }
1114 
1116  << "Relaxing " << psi_.name() << " by " << alpha << endl;
1117 
1118  Field<Type>& S = source();
1119  scalarField& D = diag();
1120 
1121  // Store the current unrelaxed diagonal for use in updating the source
1122  scalarField D0(D);
1123 
1124  // Calculate the sum-mag off-diagonal from the interior faces
1125  scalarField sumOff(D.size(), Zero);
1126  sumMagOffDiag(sumOff);
1127 
1128  // Handle the boundary contributions to the diagonal
1129  forAll(psi_.boundaryField(), patchi)
1130  {
1131  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
1132 
1133  if (ptf.size())
1134  {
1135  const labelUList& pa = lduAddr().patchAddr(patchi);
1136  Field<Type>& iCoeffs = internalCoeffs_[patchi];
1137 
1138  if (ptf.coupled())
1139  {
1140  const Field<Type>& pCoeffs = boundaryCoeffs_[patchi];
1141 
1142  // For coupled boundaries add the diagonal and
1143  // off-diagonal contributions
1144  forAll(pa, face)
1145  {
1146  D[pa[face]] += component(iCoeffs[face], 0);
1147  sumOff[pa[face]] += mag(component(pCoeffs[face], 0));
1148  }
1149  }
1150  else
1151  {
1152  // For non-coupled boundaries add the maximum magnitude diagonal
1153  // contribution to ensure stability
1154  forAll(pa, face)
1155  {
1156  D[pa[face]] += cmptMax(cmptMag(iCoeffs[face]));
1157  }
1158  }
1159  }
1160  }
1161 
1162 
1163  if (debug)
1164  {
1165  // Calculate amount of non-dominance.
1166  label nNon = 0;
1167  scalar maxNon = 0.0;
1168  scalar sumNon = 0.0;
1169  forAll(D, celli)
1170  {
1171  scalar d = (sumOff[celli] - D[celli])/mag(D[celli]);
1172 
1173  if (d > 0)
1174  {
1175  nNon++;
1176  maxNon = max(maxNon, d);
1177  sumNon += d;
1178  }
1179  }
1180 
1181  reduce(nNon, sumOp<label>(), UPstream::msgType(), psi_.mesh().comm());
1182  reduce
1183  (
1184  maxNon,
1185  maxOp<scalar>(),
1187  psi_.mesh().comm()
1188  );
1189  reduce
1190  (
1191  sumNon,
1192  sumOp<scalar>(),
1194  psi_.mesh().comm()
1195  );
1196  sumNon /= returnReduce
1197  (
1198  D.size(),
1199  sumOp<label>(),
1201  psi_.mesh().comm()
1202  );
1203 
1205  << "Matrix dominance test for " << psi_.name() << nl
1206  << " number of non-dominant cells : " << nNon << nl
1207  << " maximum relative non-dominance : " << maxNon << nl
1208  << " average relative non-dominance : " << sumNon << nl
1209  << endl;
1210  }
1211 
1212 
1213  // Ensure the matrix is diagonally dominant...
1214  // Assumes that the central coefficient is positive and ensures it is
1215  forAll(D, celli)
1216  {
1217  D[celli] = max(mag(D[celli]), sumOff[celli]);
1218  }
1219 
1220  // ... then relax
1221  D /= alpha;
1222 
1223  // Now remove the diagonal contribution from coupled boundaries
1224  forAll(psi_.boundaryField(), patchi)
1225  {
1226  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
1227 
1228  if (ptf.size())
1229  {
1230  const labelUList& pa = lduAddr().patchAddr(patchi);
1231  Field<Type>& iCoeffs = internalCoeffs_[patchi];
1232 
1233  if (ptf.coupled())
1234  {
1235  forAll(pa, face)
1236  {
1237  D[pa[face]] -= component(iCoeffs[face], 0);
1238  }
1239  }
1240  else
1241  {
1242  forAll(pa, face)
1243  {
1244  D[pa[face]] -= cmptMin(iCoeffs[face]);
1245  }
1246  }
1247  }
1248  }
1250  // Finally add the relaxation contribution to the source.
1251  S += (D - D0)*psi_.primitiveField();
1252 }
1253 
1254 
1255 template<class Type>
1257 {
1258  word name = psi_.select
1259  (
1260  psi_.mesh().data::template getOrDefault<bool>
1261  ("finalIteration", false)
1262  );
1263 
1264  if (psi_.mesh().relaxEquation(name))
1265  {
1266  relax(psi_.mesh().equationRelaxationFactor(name));
1267  }
1268 }
1269 
1270 
1271 template<class Type>
1273 (
1274  typename GeometricField<Type, fvPatchField, volMesh>::
1275  Boundary& bFields
1276 )
1277 {
1278  forAll(bFields, patchi)
1279  {
1280  bFields[patchi].manipulateMatrix(*this);
1281  }
1282 }
1283 
1284 
1285 template<class Type>
1287 {
1288  auto tdiag = tmp<scalarField>::New(diag());
1289  addCmptAvBoundaryDiag(tdiag.ref());
1290  return tdiag;
1291 }
1292 
1293 
1294 template<class Type>
1296 {
1298 
1299  forAll(psi_.boundaryField(), patchi)
1300  {
1301  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
1302 
1303  if (!ptf.coupled() && ptf.size())
1304  {
1305  addToInternalField
1306  (
1307  lduAddr().patchAddr(patchi),
1308  internalCoeffs_[patchi],
1309  tdiag.ref()
1310  );
1311  }
1312  }
1313 
1314  return tdiag;
1315 }
1316 
1317 
1318 template<class Type>
1320 {
1321  auto tAphi = volScalarField::New
1322  (
1323  "A(" + psi_.name() + ')',
1324  psi_.mesh(),
1325  dimensions_/psi_.dimensions()/dimVol,
1327  );
1328 
1329  tAphi.ref().primitiveFieldRef() = D()/psi_.mesh().V();
1330  tAphi.ref().correctBoundaryConditions();
1332  return tAphi;
1333 }
1334 
1335 
1336 template<class Type>
1339 {
1341  (
1342  "H(" + psi_.name() + ')',
1343  psi_.mesh(),
1344  dimensions_/dimVol,
1346  );
1347  auto& Hphi = tHphi.ref();
1348 
1349  // Loop over field components
1350  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
1351  {
1352  scalarField psiCmpt(psi_.primitiveField().component(cmpt));
1353 
1354  scalarField boundaryDiagCmpt(psi_.size(), Zero);
1355  addBoundaryDiag(boundaryDiagCmpt, cmpt);
1356  boundaryDiagCmpt.negate();
1357  addCmptAvBoundaryDiag(boundaryDiagCmpt);
1358 
1359  Hphi.primitiveFieldRef().replace(cmpt, boundaryDiagCmpt*psiCmpt);
1360  }
1361 
1362  Hphi.primitiveFieldRef() += lduMatrix::H(psi_.primitiveField()) + source_;
1363  addBoundarySource(Hphi.primitiveFieldRef());
1364 
1365  Hphi.primitiveFieldRef() /= psi_.mesh().V();
1367 
1368  typename Type::labelType validComponents
1369  (
1370  psi_.mesh().template validComponents<Type>()
1371  );
1372 
1373  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
1374  {
1375  if (validComponents[cmpt] == -1)
1376  {
1377  Hphi.replace
1378  (
1379  cmpt,
1381  );
1382  }
1383  }
1384 
1385  return tHphi;
1386 }
1387 
1388 
1389 template<class Type>
1391 {
1392  auto tH1 = volScalarField::New
1393  (
1394  "H(1)",
1395  psi_.mesh(),
1396  dimensions_/(dimVol*psi_.dimensions()),
1398  );
1399  auto& H1_ = tH1.ref();
1400 
1401  H1_.primitiveFieldRef() = lduMatrix::H1();
1402 
1403  forAll(psi_.boundaryField(), patchi)
1404  {
1405  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
1406 
1407  if (ptf.coupled() && ptf.size())
1408  {
1409  addToInternalField
1410  (
1411  lduAddr().patchAddr(patchi),
1412  boundaryCoeffs_[patchi].component(0),
1413  H1_
1414  );
1415  }
1416  }
1417 
1418  H1_.primitiveFieldRef() /= psi_.mesh().V();
1419  H1_.correctBoundaryConditions();
1420 
1421  return tH1;
1422 }
1423 
1424 
1425 template<class Type>
1428 flux() const
1429 {
1430  if (!psi_.mesh().fluxRequired(psi_.name()))
1431  {
1433  << "flux requested but " << psi_.name()
1434  << " not specified in the fluxRequired sub-dictionary"
1435  " of fvSchemes."
1436  << abort(FatalError);
1437  }
1438 
1439  if (nMatrices() > 1)
1440  {
1442  << "Flux requested but " << psi_.name()
1443  << " can't handle multiple fvMatrix."
1444  << abort(FatalError);
1445  }
1446 
1448  (
1449  "flux(" + psi_.name() + ')',
1450  psi_.mesh(),
1451  dimensions()
1452  );
1453  auto& fieldFlux = tfieldFlux.ref();
1454 
1455  fieldFlux.setOriented();
1456 
1457  for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
1458  {
1459  fieldFlux.primitiveFieldRef().replace
1460  (
1461  cmpt,
1462  lduMatrix::faceH(psi_.primitiveField().component(cmpt))
1463  );
1464  }
1465 
1466  FieldField<Field, Type> InternalContrib = internalCoeffs_;
1467 
1468  label fieldi = 0;
1469  if (!useImplicit_)
1470  {
1471  forAll(InternalContrib, patchi)
1472  {
1473  InternalContrib[patchi] =
1474  cmptMultiply
1475  (
1476  InternalContrib[patchi],
1477  psi_.boundaryField()[patchi].patchInternalField()
1478  );
1479  }
1480  }
1481  else
1482  {
1483  FieldField<Field, Type> fluxInternalContrib(internalCoeffs_);
1484 
1485  mapContributions(fieldi, fluxInternalContrib, InternalContrib, true);
1486  }
1487 
1488  FieldField<Field, Type> NeighbourContrib = boundaryCoeffs_;
1489 
1490  if (!useImplicit_)
1491  {
1492  forAll(NeighbourContrib, patchi)
1493  {
1494  if (psi_.boundaryField()[patchi].coupled())
1495  {
1496  NeighbourContrib[patchi] =
1497  cmptMultiply
1498  (
1499  NeighbourContrib[patchi],
1500  psi_.boundaryField()[patchi].patchNeighbourField()
1501  );
1502  }
1503  }
1504  }
1505  else
1506  {
1507  FieldField<Field, Type> fluxBoundaryContrib(boundaryCoeffs_);
1508 
1509  mapContributions(fieldi, fluxBoundaryContrib, NeighbourContrib, false);
1510  }
1511 
1512  typename GeometricField<Type, fvsPatchField, surfaceMesh>::
1513  Boundary& ffbf = fieldFlux.boundaryFieldRef();
1514 
1515  forAll(ffbf, patchi)
1516  {
1517  ffbf[patchi] = InternalContrib[patchi] - NeighbourContrib[patchi];
1518  //DebugVar(gSum(ffbf[patchi]))
1519  }
1520 
1521  if (faceFluxCorrectionPtr_)
1522  {
1523  fieldFlux += *faceFluxCorrectionPtr_;
1524  }
1525 
1526  return tfieldFlux;
1527 }
1528 
1529 
1530 template<class Type>
1532 {
1533  return psi_.mesh().solverDict
1534  (
1535  psi_.select
1536  (
1537  psi_.mesh().data::template getOrDefault<bool>
1538  ("finalIteration", false)
1539  )
1540  );
1541 }
1542 
1543 
1544 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1545 
1546 template<class Type>
1548 {
1549  if (this == &fvmv)
1550  {
1551  return; // Self-assignment is a no-op
1552  }
1553 
1554  if (&psi_ != &(fvmv.psi_))
1555  {
1557  << "different fields"
1558  << abort(FatalError);
1559  }
1560 
1561  dimensions_ = fvmv.dimensions_;
1562  lduMatrix::operator=(fvmv);
1563  source_ = fvmv.source_;
1564  internalCoeffs_ = fvmv.internalCoeffs_;
1565  boundaryCoeffs_ = fvmv.boundaryCoeffs_;
1566 
1567  if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
1568  {
1569  *faceFluxCorrectionPtr_ = *fvmv.faceFluxCorrectionPtr_;
1570  }
1571  else if (fvmv.faceFluxCorrectionPtr_)
1572  {
1573  faceFluxCorrectionPtr_ =
1574  new GeometricField<Type, fvsPatchField, surfaceMesh>
1575  (*fvmv.faceFluxCorrectionPtr_);
1576  }
1578  useImplicit_ = fvmv.useImplicit_;
1579  lduAssemblyName_ = fvmv.lduAssemblyName_;
1580 }
1581 
1582 
1583 template<class Type>
1586  operator=(tfvmv());
1587  tfvmv.clear();
1588 }
1589 
1590 
1591 template<class Type>
1593 {
1595  source_.negate();
1596  internalCoeffs_.negate();
1597  boundaryCoeffs_.negate();
1598 
1599  if (faceFluxCorrectionPtr_)
1600  {
1601  faceFluxCorrectionPtr_->negate();
1602  }
1603 }
1604 
1605 
1606 template<class Type>
1607 void Foam::fvMatrix<Type>::operator+=(const fvMatrix<Type>& fvmv)
1608 {
1609  checkMethod(*this, fvmv, "+=");
1610 
1611  dimensions_ += fvmv.dimensions_;
1612  lduMatrix::operator+=(fvmv);
1613  source_ += fvmv.source_;
1614  internalCoeffs_ += fvmv.internalCoeffs_;
1615  boundaryCoeffs_ += fvmv.boundaryCoeffs_;
1616 
1617  useImplicit_ = fvmv.useImplicit_;
1618  lduAssemblyName_ = fvmv.lduAssemblyName_;
1619  nMatrix_ = fvmv.nMatrix_;
1620 
1621  if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
1622  {
1623  *faceFluxCorrectionPtr_ += *fvmv.faceFluxCorrectionPtr_;
1624  }
1625  else if (fvmv.faceFluxCorrectionPtr_)
1626  {
1627  faceFluxCorrectionPtr_ = new
1628  GeometricField<Type, fvsPatchField, surfaceMesh>
1629  (
1630  *fvmv.faceFluxCorrectionPtr_
1631  );
1632  }
1633 }
1634 
1635 
1636 template<class Type>
1637 void Foam::fvMatrix<Type>::operator+=(const tmp<fvMatrix<Type>>& tfvmv)
1639  operator+=(tfvmv());
1640  tfvmv.clear();
1641 }
1642 
1643 
1644 template<class Type>
1646 {
1647  checkMethod(*this, fvmv, "-=");
1648 
1649  dimensions_ -= fvmv.dimensions_;
1650  lduMatrix::operator-=(fvmv);
1651  source_ -= fvmv.source_;
1652  internalCoeffs_ -= fvmv.internalCoeffs_;
1653  boundaryCoeffs_ -= fvmv.boundaryCoeffs_;
1654 
1655  useImplicit_ = fvmv.useImplicit_;
1656  lduAssemblyName_ = fvmv.lduAssemblyName_;
1657  nMatrix_ = fvmv.nMatrix_;
1658 
1659  if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
1660  {
1661  *faceFluxCorrectionPtr_ -= *fvmv.faceFluxCorrectionPtr_;
1662  }
1663  else if (fvmv.faceFluxCorrectionPtr_)
1664  {
1665  faceFluxCorrectionPtr_ =
1667  (-*fvmv.faceFluxCorrectionPtr_);
1668  }
1669 }
1670 
1671 
1672 template<class Type>
1673 void Foam::fvMatrix<Type>::operator-=(const tmp<fvMatrix<Type>>& tfvmv)
1674 {
1675  operator-=(tfvmv());
1676  tfvmv.clear();
1677 }
1678 
1679 
1680 template<class Type>
1682 (
1684 )
1685 {
1686  checkMethod(*this, su, "+=");
1687  source() -= su.mesh().V()*su.field();
1688 }
1689 
1690 
1691 template<class Type>
1693 (
1695 )
1696 {
1697  operator+=(tsu());
1698  tsu.clear();
1699 }
1700 
1701 
1702 template<class Type>
1704 (
1706 )
1707 {
1708  operator+=(tsu());
1709  tsu.clear();
1710 }
1711 
1712 
1713 template<class Type>
1715 (
1717 )
1718 {
1719  checkMethod(*this, su, "-=");
1720  source() += su.mesh().V()*su.field();
1721 }
1722 
1723 
1724 template<class Type>
1726 (
1728 )
1729 {
1730  operator-=(tsu());
1731  tsu.clear();
1732 }
1733 
1734 
1735 template<class Type>
1737 (
1739 )
1740 {
1741  operator-=(tsu());
1742  tsu.clear();
1743 }
1744 
1745 
1746 template<class Type>
1748 (
1749  const dimensioned<Type>& su
1750 )
1752  source() -= psi().mesh().V()*su;
1753 }
1754 
1755 
1756 template<class Type>
1758 (
1759  const dimensioned<Type>& su
1761 {
1762  source() += psi().mesh().V()*su;
1763 }
1764 
1766 template<class Type>
1768 {}
1769 
1770 
1771 template<class Type>
1773 {}
1774 
1775 
1776 template<class Type>
1778 (
1779  const volScalarField::Internal& dsf
1780 )
1781 {
1782  dimensions_ *= dsf.dimensions();
1783  lduMatrix::operator*=(dsf.field());
1784  source_ *= dsf.field();
1785 
1786  forAll(boundaryCoeffs_, patchi)
1787  {
1788  scalarField pisf
1789  (
1790  dsf.mesh().boundary()[patchi].patchInternalField(dsf.field())
1791  );
1792 
1793  internalCoeffs_[patchi] *= pisf;
1794  boundaryCoeffs_[patchi] *= pisf;
1795  }
1796 
1797  if (faceFluxCorrectionPtr_)
1798  {
1800  << "cannot scale a matrix containing a faceFluxCorrection"
1802  }
1803 }
1804 
1805 
1806 template<class Type>
1808 (
1809  const tmp<volScalarField::Internal>& tfld
1810 )
1811 {
1812  operator*=(tfld());
1813  tfld.clear();
1814 }
1815 
1816 
1817 template<class Type>
1819 (
1820  const tmp<volScalarField>& tfld
1821 )
1822 {
1823  operator*=(tfld());
1824  tfld.clear();
1825 }
1826 
1827 
1828 template<class Type>
1830 (
1831  const dimensioned<scalar>& ds
1832 )
1833 {
1834  dimensions_ *= ds.dimensions();
1835  lduMatrix::operator*=(ds.value());
1836  source_ *= ds.value();
1837  internalCoeffs_ *= ds.value();
1838  boundaryCoeffs_ *= ds.value();
1839 
1840  if (faceFluxCorrectionPtr_)
1841  {
1842  *faceFluxCorrectionPtr_ *= ds.value();
1843  }
1845 
1846 
1847 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
1848 
1849 template<class Type>
1850 void Foam::checkMethod
1851 (
1852  const fvMatrix<Type>& mat1,
1853  const fvMatrix<Type>& mat2,
1854  const char* op
1855 )
1856 {
1857  if (&mat1.psi() != &mat2.psi())
1858  {
1860  << "Incompatible fields for operation\n "
1861  << "[" << mat1.psi().name() << "] "
1862  << op
1863  << " [" << mat2.psi().name() << "]"
1864  << abort(FatalError);
1865  }
1866 
1867  if
1868  (
1870  && mat1.dimensions() != mat2.dimensions()
1871  )
1872  {
1874  << "Incompatible dimensions for operation\n "
1875  << "[" << mat1.psi().name() << mat1.dimensions()/dimVolume << " ] "
1876  << op
1877  << " [" << mat2.psi().name() << mat2.dimensions()/dimVolume << " ]"
1879  }
1880 }
1881 
1882 
1883 template<class Type>
1884 void Foam::checkMethod
1885 (
1886  const fvMatrix<Type>& mat,
1887  const DimensionedField<Type, volMesh>& fld,
1888  const char* op
1889 )
1890 {
1891  if
1892  (
1894  && mat.dimensions()/dimVolume != fld.dimensions()
1895  )
1896  {
1898  << "Incompatible dimensions for operation\n "
1899  << "[" << mat.psi().name() << mat.dimensions()/dimVolume << " ] "
1900  << op
1901  << " [" << fld.name() << fld.dimensions() << " ]"
1903  }
1904 }
1905 
1906 
1907 template<class Type>
1908 void Foam::checkMethod
1909 (
1910  const fvMatrix<Type>& mat,
1911  const dimensioned<Type>& dt,
1912  const char* op
1913 )
1914 {
1915  if
1916  (
1918  && mat.dimensions()/dimVolume != dt.dimensions()
1919  )
1920  {
1922  << "Incompatible dimensions for operation\n "
1923  << "[" << mat.psi().name() << mat.dimensions()/dimVolume << " ] "
1924  << op
1925  << " [" << dt.name() << dt.dimensions() << " ]"
1926  << abort(FatalError);
1927  }
1928 }
1929 
1930 
1931 template<class Type>
1933 (
1934  fvMatrix<Type>& fvm,
1935  const dictionary& solverControls
1936 )
1937 {
1938  return fvm.solve(solverControls);
1939 }
1940 
1941 template<class Type>
1943 (
1944  const tmp<fvMatrix<Type>>& tmat,
1945  const dictionary& solverControls
1946 )
1947 {
1948  SolverPerformance<Type> solverPerf(tmat.constCast().solve(solverControls));
1949 
1950  tmat.clear();
1951 
1952  return solverPerf;
1953 }
1954 
1955 
1956 template<class Type>
1957 Foam::SolverPerformance<Type> Foam::solve(fvMatrix<Type>& fvm)
1958 {
1959  return fvm.solve();
1960 }
1961 
1962 template<class Type>
1963 Foam::SolverPerformance<Type> Foam::solve(const tmp<fvMatrix<Type>>& tmat)
1964 {
1965  SolverPerformance<Type> solverPerf(tmat.constCast().solve());
1966 
1967  tmat.clear();
1968 
1969  return solverPerf;
1970 }
1971 
1972 
1973 template<class Type>
1975 (
1976  const fvMatrix<Type>& A
1977 )
1978 {
1979  tmp<Foam::fvMatrix<Type>> tAcorr = A - (A & A.psi());
1980 
1981  // Delete the faceFluxCorrection from the correction matrix
1982  // as it does not have a clear meaning or purpose
1983  deleteDemandDrivenData(tAcorr.ref().faceFluxCorrectionPtr());
1984 
1985  return tAcorr;
1986 }
1987 
1988 
1989 template<class Type>
1991 (
1992  const tmp<fvMatrix<Type>>& tA
1993 )
1994 {
1995  tmp<Foam::fvMatrix<Type>> tAcorr = tA - (tA() & tA().psi());
1996 
1997  // Delete the faceFluxCorrection from the correction matrix
1998  // as it does not have a clear meaning or purpose
1999  deleteDemandDrivenData(tAcorr.ref().faceFluxCorrectionPtr());
2000 
2001  return tAcorr;
2002 }
2003 
2004 
2005 // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
2006 
2007 template<class Type>
2008 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2009 (
2010  const fvMatrix<Type>& A,
2011  const fvMatrix<Type>& B
2012 )
2013 {
2014  checkMethod(A, B, "==");
2015  return (A - B);
2016 }
2017 
2018 template<class Type>
2019 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2020 (
2021  const tmp<fvMatrix<Type>>& tA,
2022  const fvMatrix<Type>& B
2023 )
2024 {
2025  checkMethod(tA(), B, "==");
2026  return (tA - B);
2027 }
2028 
2029 template<class Type>
2030 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2031 (
2032  const fvMatrix<Type>& A,
2033  const tmp<fvMatrix<Type>>& tB
2034 )
2035 {
2036  checkMethod(A, tB(), "==");
2037  return (A - tB);
2038 }
2039 
2040 template<class Type>
2041 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2042 (
2043  const tmp<fvMatrix<Type>>& tA,
2044  const tmp<fvMatrix<Type>>& tB
2045 )
2046 {
2047  checkMethod(tA(), tB(), "==");
2048  return (tA - tB);
2049 }
2050 
2051 template<class Type>
2052 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2053 (
2054  const fvMatrix<Type>& A,
2055  const DimensionedField<Type, volMesh>& su
2056 )
2057 {
2058  checkMethod(A, su, "==");
2059  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2060  tC.ref().source() += su.mesh().V()*su.field();
2061  return tC;
2062 }
2063 
2064 template<class Type>
2065 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2066 (
2067  const fvMatrix<Type>& A,
2068  const tmp<DimensionedField<Type, volMesh>>& tsu
2069 )
2070 {
2071  checkMethod(A, tsu(), "==");
2072  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2073  tC.ref().source() += tsu().mesh().V()*tsu().field();
2074  tsu.clear();
2075  return tC;
2076 }
2077 
2078 template<class Type>
2079 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2080 (
2081  const fvMatrix<Type>& A,
2082  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2083 )
2084 {
2085  checkMethod(A, tsu(), "==");
2086  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2087  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2088  tsu.clear();
2089  return tC;
2090 }
2091 
2092 template<class Type>
2093 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2094 (
2095  const tmp<fvMatrix<Type>>& tA,
2096  const DimensionedField<Type, volMesh>& su
2097 )
2098 {
2099  checkMethod(tA(), su, "==");
2100  tmp<fvMatrix<Type>> tC(tA.ptr());
2101  tC.ref().source() += su.mesh().V()*su.field();
2102  return tC;
2103 }
2104 
2105 template<class Type>
2106 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2107 (
2108  const tmp<fvMatrix<Type>>& tA,
2109  const tmp<DimensionedField<Type, volMesh>>& tsu
2110 )
2111 {
2112  checkMethod(tA(), tsu(), "==");
2113  tmp<fvMatrix<Type>> tC(tA.ptr());
2114  tC.ref().source() += tsu().mesh().V()*tsu().field();
2115  tsu.clear();
2116  return tC;
2117 }
2118 
2119 template<class Type>
2120 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2121 (
2122  const tmp<fvMatrix<Type>>& tA,
2123  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2124 )
2125 {
2126  checkMethod(tA(), tsu(), "==");
2127  tmp<fvMatrix<Type>> tC(tA.ptr());
2128  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2129  tsu.clear();
2130  return tC;
2131 }
2132 
2133 template<class Type>
2134 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2135 (
2136  const fvMatrix<Type>& A,
2137  const dimensioned<Type>& su
2138 )
2139 {
2140  checkMethod(A, su, "==");
2141  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2142  tC.ref().source() += A.psi().mesh().V()*su.value();
2143  return tC;
2144 }
2145 
2146 template<class Type>
2147 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2148 (
2149  const tmp<fvMatrix<Type>>& tA,
2150  const dimensioned<Type>& su
2151 )
2152 {
2153  checkMethod(tA(), su, "==");
2154  tmp<fvMatrix<Type>> tC(tA.ptr());
2155  tC.ref().source() += tC().psi().mesh().V()*su.value();
2156  return tC;
2157 }
2158 
2159 template<class Type>
2160 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2161 (
2162  const fvMatrix<Type>& A,
2163  const Foam::zero
2164 )
2165 {
2166  return A;
2167 }
2168 
2169 
2170 template<class Type>
2171 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2172 (
2173  const tmp<fvMatrix<Type>>& tA,
2174  const Foam::zero
2175 )
2176 {
2177  return tA;
2178 }
2179 
2180 
2181 template<class Type>
2182 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2183 (
2184  const fvMatrix<Type>& A
2185 )
2186 {
2187  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2188  tC.ref().negate();
2189  return tC;
2190 }
2191 
2192 template<class Type>
2193 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2194 (
2195  const tmp<fvMatrix<Type>>& tA
2196 )
2197 {
2198  tmp<fvMatrix<Type>> tC(tA.ptr());
2199  tC.ref().negate();
2200  return tC;
2201 }
2202 
2203 
2204 template<class Type>
2205 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2206 (
2207  const fvMatrix<Type>& A,
2208  const fvMatrix<Type>& B
2209 )
2210 {
2211  checkMethod(A, B, "+");
2212  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2213  tC.ref() += B;
2214  return tC;
2215 }
2216 
2217 template<class Type>
2218 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2219 (
2220  const tmp<fvMatrix<Type>>& tA,
2221  const fvMatrix<Type>& B
2222 )
2223 {
2224  checkMethod(tA(), B, "+");
2225  tmp<fvMatrix<Type>> tC(tA.ptr());
2226  tC.ref() += B;
2227  return tC;
2228 }
2229 
2230 template<class Type>
2231 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2232 (
2233  const fvMatrix<Type>& A,
2234  const tmp<fvMatrix<Type>>& tB
2235 )
2236 {
2237  checkMethod(A, tB(), "+");
2238  tmp<fvMatrix<Type>> tC(tB.ptr());
2239  tC.ref() += A;
2240  return tC;
2241 }
2242 
2243 template<class Type>
2244 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2245 (
2246  const tmp<fvMatrix<Type>>& tA,
2247  const tmp<fvMatrix<Type>>& tB
2248 )
2249 {
2250  checkMethod(tA(), tB(), "+");
2251  tmp<fvMatrix<Type>> tC(tA.ptr());
2252  tC.ref() += tB();
2253  tB.clear();
2254  return tC;
2255 }
2256 
2257 template<class Type>
2258 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2259 (
2260  const fvMatrix<Type>& A,
2261  const DimensionedField<Type, volMesh>& su
2262 )
2263 {
2264  checkMethod(A, su, "+");
2265  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2266  tC.ref().source() -= su.mesh().V()*su.field();
2267  return tC;
2268 }
2269 
2270 template<class Type>
2271 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2272 (
2273  const fvMatrix<Type>& A,
2274  const tmp<DimensionedField<Type, volMesh>>& tsu
2275 )
2276 {
2277  checkMethod(A, tsu(), "+");
2278  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2279  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2280  tsu.clear();
2281  return tC;
2282 }
2283 
2284 template<class Type>
2285 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2286 (
2287  const fvMatrix<Type>& A,
2288  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2289 )
2290 {
2291  checkMethod(A, tsu(), "+");
2292  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2293  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2294  tsu.clear();
2295  return tC;
2296 }
2297 
2298 template<class Type>
2299 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2300 (
2301  const tmp<fvMatrix<Type>>& tA,
2302  const DimensionedField<Type, volMesh>& su
2303 )
2304 {
2305  checkMethod(tA(), su, "+");
2306  tmp<fvMatrix<Type>> tC(tA.ptr());
2307  tC.ref().source() -= su.mesh().V()*su.field();
2308  return tC;
2309 }
2310 
2311 template<class Type>
2312 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2313 (
2314  const tmp<fvMatrix<Type>>& tA,
2315  const tmp<DimensionedField<Type, volMesh>>& tsu
2316 )
2317 {
2318  checkMethod(tA(), tsu(), "+");
2319  tmp<fvMatrix<Type>> tC(tA.ptr());
2320  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2321  tsu.clear();
2322  return tC;
2323 }
2324 
2325 template<class Type>
2326 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2327 (
2328  const tmp<fvMatrix<Type>>& tA,
2329  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2330 )
2331 {
2332  checkMethod(tA(), tsu(), "+");
2333  tmp<fvMatrix<Type>> tC(tA.ptr());
2334  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2335  tsu.clear();
2336  return tC;
2337 }
2338 
2339 template<class Type>
2340 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2341 (
2342  const DimensionedField<Type, volMesh>& su,
2343  const fvMatrix<Type>& A
2344 )
2345 {
2346  checkMethod(A, su, "+");
2347  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2348  tC.ref().source() -= su.mesh().V()*su.field();
2349  return tC;
2350 }
2351 
2352 template<class Type>
2353 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2354 (
2355  const tmp<DimensionedField<Type, volMesh>>& tsu,
2356  const fvMatrix<Type>& A
2357 )
2358 {
2359  checkMethod(A, tsu(), "+");
2360  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2361  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2362  tsu.clear();
2363  return tC;
2364 }
2365 
2366 template<class Type>
2367 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2368 (
2369  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu,
2370  const fvMatrix<Type>& A
2371 )
2372 {
2373  checkMethod(A, tsu(), "+");
2374  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2375  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2376  tsu.clear();
2377  return tC;
2378 }
2379 
2380 template<class Type>
2381 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2382 (
2383  const DimensionedField<Type, volMesh>& su,
2384  const tmp<fvMatrix<Type>>& tA
2385 )
2386 {
2387  checkMethod(tA(), su, "+");
2388  tmp<fvMatrix<Type>> tC(tA.ptr());
2389  tC.ref().source() -= su.mesh().V()*su.field();
2390  return tC;
2391 }
2392 
2393 template<class Type>
2394 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2395 (
2396  const tmp<DimensionedField<Type, volMesh>>& tsu,
2397  const tmp<fvMatrix<Type>>& tA
2398 )
2399 {
2400  checkMethod(tA(), tsu(), "+");
2401  tmp<fvMatrix<Type>> tC(tA.ptr());
2402  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2403  tsu.clear();
2404  return tC;
2405 }
2406 
2407 template<class Type>
2408 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2409 (
2410  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu,
2411  const tmp<fvMatrix<Type>>& tA
2412 )
2413 {
2414  checkMethod(tA(), tsu(), "+");
2415  tmp<fvMatrix<Type>> tC(tA.ptr());
2416  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2417  tsu.clear();
2418  return tC;
2419 }
2420 
2421 
2422 template<class Type>
2423 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2424 (
2425  const fvMatrix<Type>& A,
2426  const fvMatrix<Type>& B
2427 )
2428 {
2429  checkMethod(A, B, "-");
2430  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2431  tC.ref() -= B;
2432  return tC;
2433 }
2434 
2435 template<class Type>
2436 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2437 (
2438  const tmp<fvMatrix<Type>>& tA,
2439  const fvMatrix<Type>& B
2440 )
2441 {
2442  checkMethod(tA(), B, "-");
2443  tmp<fvMatrix<Type>> tC(tA.ptr());
2444  tC.ref() -= B;
2445  return tC;
2446 }
2447 
2448 template<class Type>
2449 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2450 (
2451  const fvMatrix<Type>& A,
2452  const tmp<fvMatrix<Type>>& tB
2453 )
2454 {
2455  checkMethod(A, tB(), "-");
2456  tmp<fvMatrix<Type>> tC(tB.ptr());
2457  tC.ref() -= A;
2458  tC.ref().negate();
2459  return tC;
2460 }
2461 
2462 template<class Type>
2463 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2464 (
2465  const tmp<fvMatrix<Type>>& tA,
2466  const tmp<fvMatrix<Type>>& tB
2467 )
2468 {
2469  checkMethod(tA(), tB(), "-");
2470  tmp<fvMatrix<Type>> tC(tA.ptr());
2471  tC.ref() -= tB();
2472  tB.clear();
2473  return tC;
2474 }
2475 
2476 template<class Type>
2477 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2478 (
2479  const fvMatrix<Type>& A,
2480  const DimensionedField<Type, volMesh>& su
2481 )
2482 {
2483  checkMethod(A, su, "-");
2484  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2485  tC.ref().source() += su.mesh().V()*su.field();
2486  return tC;
2487 }
2488 
2489 template<class Type>
2490 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2491 (
2492  const fvMatrix<Type>& A,
2493  const tmp<DimensionedField<Type, volMesh>>& tsu
2494 )
2495 {
2496  checkMethod(A, tsu(), "-");
2497  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2498  tC.ref().source() += tsu().mesh().V()*tsu().field();
2499  tsu.clear();
2500  return tC;
2501 }
2502 
2503 template<class Type>
2504 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2505 (
2506  const fvMatrix<Type>& A,
2507  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2508 )
2509 {
2510  checkMethod(A, tsu(), "-");
2511  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2512  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2513  tsu.clear();
2514  return tC;
2515 }
2516 
2517 template<class Type>
2518 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2519 (
2520  const tmp<fvMatrix<Type>>& tA,
2521  const DimensionedField<Type, volMesh>& su
2522 )
2523 {
2524  checkMethod(tA(), su, "-");
2525  tmp<fvMatrix<Type>> tC(tA.ptr());
2526  tC.ref().source() += su.mesh().V()*su.field();
2527  return tC;
2528 }
2529 
2530 template<class Type>
2531 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2532 (
2533  const tmp<fvMatrix<Type>>& tA,
2534  const tmp<DimensionedField<Type, volMesh>>& tsu
2535 )
2536 {
2537  checkMethod(tA(), tsu(), "-");
2538  tmp<fvMatrix<Type>> tC(tA.ptr());
2539  tC.ref().source() += tsu().mesh().V()*tsu().field();
2540  tsu.clear();
2541  return tC;
2542 }
2543 
2544 template<class Type>
2545 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2546 (
2547  const tmp<fvMatrix<Type>>& tA,
2548  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2549 )
2550 {
2551  checkMethod(tA(), tsu(), "-");
2552  tmp<fvMatrix<Type>> tC(tA.ptr());
2553  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2554  tsu.clear();
2555  return tC;
2556 }
2557 
2558 template<class Type>
2559 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2560 (
2561  const DimensionedField<Type, volMesh>& su,
2562  const fvMatrix<Type>& A
2563 )
2564 {
2565  checkMethod(A, su, "-");
2566  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2567  tC.ref().negate();
2568  tC.ref().source() -= su.mesh().V()*su.field();
2569  return tC;
2570 }
2571 
2572 template<class Type>
2573 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2574 (
2575  const tmp<DimensionedField<Type, volMesh>>& tsu,
2576  const fvMatrix<Type>& A
2577 )
2578 {
2579  checkMethod(A, tsu(), "-");
2580  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2581  tC.ref().negate();
2582  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2583  tsu.clear();
2584  return tC;
2585 }
2586 
2587 template<class Type>
2588 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2589 (
2590  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu,
2591  const fvMatrix<Type>& A
2592 )
2593 {
2594  checkMethod(A, tsu(), "-");
2595  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2596  tC.ref().negate();
2597  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2598  tsu.clear();
2599  return tC;
2600 }
2601 
2602 template<class Type>
2603 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2604 (
2605  const DimensionedField<Type, volMesh>& su,
2606  const tmp<fvMatrix<Type>>& tA
2607 )
2608 {
2609  checkMethod(tA(), su, "-");
2610  tmp<fvMatrix<Type>> tC(tA.ptr());
2611  tC.ref().negate();
2612  tC.ref().source() -= su.mesh().V()*su.field();
2613  return tC;
2614 }
2615 
2616 template<class Type>
2617 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2618 (
2619  const tmp<DimensionedField<Type, volMesh>>& tsu,
2620  const tmp<fvMatrix<Type>>& tA
2621 )
2622 {
2623  checkMethod(tA(), tsu(), "-");
2624  tmp<fvMatrix<Type>> tC(tA.ptr());
2625  tC.ref().negate();
2626  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2627  tsu.clear();
2628  return tC;
2629 }
2630 
2631 template<class Type>
2632 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2633 (
2634  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu,
2635  const tmp<fvMatrix<Type>>& tA
2636 )
2637 {
2638  checkMethod(tA(), tsu(), "-");
2639  tmp<fvMatrix<Type>> tC(tA.ptr());
2640  tC.ref().negate();
2641  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2642  tsu.clear();
2643  return tC;
2644 }
2645 
2646 template<class Type>
2647 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2648 (
2649  const fvMatrix<Type>& A,
2650  const dimensioned<Type>& su
2651 )
2652 {
2653  checkMethod(A, su, "+");
2654  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2655  tC.ref().source() -= su.value()*A.psi().mesh().V();
2656  return tC;
2657 }
2658 
2659 template<class Type>
2660 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2661 (
2662  const tmp<fvMatrix<Type>>& tA,
2663  const dimensioned<Type>& su
2664 )
2665 {
2666  checkMethod(tA(), su, "+");
2667  tmp<fvMatrix<Type>> tC(tA.ptr());
2668  tC.ref().source() -= su.value()*tC().psi().mesh().V();
2669  return tC;
2670 }
2671 
2672 template<class Type>
2673 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2674 (
2675  const dimensioned<Type>& su,
2676  const fvMatrix<Type>& A
2677 )
2678 {
2679  checkMethod(A, su, "+");
2680  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2681  tC.ref().source() -= su.value()*A.psi().mesh().V();
2682  return tC;
2683 }
2684 
2685 template<class Type>
2686 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2687 (
2688  const dimensioned<Type>& su,
2689  const tmp<fvMatrix<Type>>& tA
2690 )
2691 {
2692  checkMethod(tA(), su, "+");
2693  tmp<fvMatrix<Type>> tC(tA.ptr());
2694  tC.ref().source() -= su.value()*tC().psi().mesh().V();
2695  return tC;
2696 }
2697 
2698 template<class Type>
2699 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2700 (
2701  const fvMatrix<Type>& A,
2702  const dimensioned<Type>& su
2703 )
2704 {
2705  checkMethod(A, su, "-");
2706  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2707  tC.ref().source() += su.value()*tC().psi().mesh().V();
2708  return tC;
2709 }
2710 
2711 template<class Type>
2712 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2713 (
2714  const tmp<fvMatrix<Type>>& tA,
2715  const dimensioned<Type>& su
2716 )
2717 {
2718  checkMethod(tA(), su, "-");
2719  tmp<fvMatrix<Type>> tC(tA.ptr());
2720  tC.ref().source() += su.value()*tC().psi().mesh().V();
2721  return tC;
2722 }
2723 
2724 template<class Type>
2725 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2726 (
2727  const dimensioned<Type>& su,
2728  const fvMatrix<Type>& A
2729 )
2730 {
2731  checkMethod(A, su, "-");
2732  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2733  tC.ref().negate();
2734  tC.ref().source() -= su.value()*A.psi().mesh().V();
2735  return tC;
2736 }
2737 
2738 template<class Type>
2739 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2740 (
2741  const dimensioned<Type>& su,
2742  const tmp<fvMatrix<Type>>& tA
2743 )
2744 {
2745  checkMethod(tA(), su, "-");
2746  tmp<fvMatrix<Type>> tC(tA.ptr());
2747  tC.ref().negate();
2748  tC.ref().source() -= su.value()*tC().psi().mesh().V();
2749  return tC;
2750 }
2751 
2752 
2753 template<class Type>
2754 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2755 (
2756  const volScalarField::Internal& dsf,
2757  const fvMatrix<Type>& A
2758 )
2759 {
2760  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2761  tC.ref() *= dsf;
2762  return tC;
2763 }
2764 
2765 template<class Type>
2766 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2767 (
2768  const tmp<volScalarField::Internal>& tdsf,
2769  const fvMatrix<Type>& A
2770 )
2771 {
2772  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2773  tC.ref() *= tdsf;
2774  return tC;
2775 }
2776 
2777 template<class Type>
2778 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2779 (
2780  const tmp<volScalarField>& tvsf,
2781  const fvMatrix<Type>& A
2782 )
2783 {
2784  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2785  tC.ref() *= tvsf;
2786  return tC;
2787 }
2788 
2789 template<class Type>
2790 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2791 (
2792  const volScalarField::Internal& dsf,
2793  const tmp<fvMatrix<Type>>& tA
2794 )
2795 {
2796  tmp<fvMatrix<Type>> tC(tA.ptr());
2797  tC.ref() *= dsf;
2798  return tC;
2799 }
2800 
2801 template<class Type>
2802 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2803 (
2804  const tmp<volScalarField::Internal>& tdsf,
2805  const tmp<fvMatrix<Type>>& tA
2806 )
2807 {
2808  tmp<fvMatrix<Type>> tC(tA.ptr());
2809  tC.ref() *= tdsf;
2810  return tC;
2811 }
2812 
2813 template<class Type>
2814 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2815 (
2816  const tmp<volScalarField>& tvsf,
2817  const tmp<fvMatrix<Type>>& tA
2818 )
2819 {
2820  tmp<fvMatrix<Type>> tC(tA.ptr());
2821  tC.ref() *= tvsf;
2822  return tC;
2823 }
2824 
2825 template<class Type>
2826 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2827 (
2828  const dimensioned<scalar>& ds,
2829  const fvMatrix<Type>& A
2830 )
2831 {
2832  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2833  tC.ref() *= ds;
2834  return tC;
2835 }
2836 
2837 template<class Type>
2838 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2839 (
2840  const dimensioned<scalar>& ds,
2841  const tmp<fvMatrix<Type>>& tA
2842 )
2843 {
2844  tmp<fvMatrix<Type>> tC(tA.ptr());
2845  tC.ref() *= ds;
2846  return tC;
2847 }
2848 
2849 
2850 template<class Type>
2852 Foam::operator&
2853 (
2854  const fvMatrix<Type>& M,
2855  const DimensionedField<Type, volMesh>& psi
2856 )
2857 {
2859  (
2860  "M&" + psi.name(),
2861  psi.mesh(),
2862  M.dimensions()/dimVol,
2864  );
2865  auto& Mphi = tMphi.ref();
2866 
2867  // Loop over field components
2868  if (M.hasDiag())
2869  {
2870  for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
2871  {
2872  scalarField psiCmpt(psi.field().component(cmpt));
2873  scalarField boundaryDiagCmpt(M.diag());
2874  M.addBoundaryDiag(boundaryDiagCmpt, cmpt);
2875  Mphi.primitiveFieldRef().replace(cmpt, -boundaryDiagCmpt*psiCmpt);
2876  }
2877  }
2878  else
2879  {
2880  Mphi.primitiveFieldRef() = Zero;
2881  }
2882 
2883  Mphi.primitiveFieldRef() += M.lduMatrix::H(psi.field()) + M.source();
2884  M.addBoundarySource(Mphi.primitiveFieldRef());
2885 
2886  Mphi.primitiveFieldRef() /= -psi.mesh().V();
2887  Mphi.correctBoundaryConditions();
2888 
2889  return tMphi;
2890 }
2891 
2892 template<class Type>
2894 Foam::operator&
2895 (
2896  const fvMatrix<Type>& M,
2897  const tmp<DimensionedField<Type, volMesh>>& tpsi
2898 )
2899 {
2900  tmp<GeometricField<Type, fvPatchField, volMesh>> tMpsi = M & tpsi();
2901  tpsi.clear();
2902  return tMpsi;
2903 }
2904 
2905 template<class Type>
2907 Foam::operator&
2908 (
2909  const fvMatrix<Type>& M,
2910  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tpsi
2911 )
2912 {
2913  tmp<GeometricField<Type, fvPatchField, volMesh>> tMpsi = M & tpsi();
2914  tpsi.clear();
2915  return tMpsi;
2916 }
2917 
2918 template<class Type>
2920 Foam::operator&
2921 (
2922  const tmp<fvMatrix<Type>>& tM,
2923  const DimensionedField<Type, volMesh>& psi
2924 )
2925 {
2926  tmp<GeometricField<Type, fvPatchField, volMesh>> tMpsi = tM() & psi;
2927  tM.clear();
2928  return tMpsi;
2929 }
2930 
2931 template<class Type>
2933 Foam::operator&
2934 (
2935  const tmp<fvMatrix<Type>>& tM,
2936  const tmp<DimensionedField<Type, volMesh>>& tpsi
2937 )
2938 {
2939  tmp<GeometricField<Type, fvPatchField, volMesh>> tMpsi = tM() & tpsi();
2940  tM.clear();
2941  tpsi.clear();
2942  return tMpsi;
2943 }
2944 
2945 template<class Type>
2947 Foam::operator&
2948 (
2949  const tmp<fvMatrix<Type>>& tM,
2950  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tpsi
2951 )
2952 {
2953  tmp<GeometricField<Type, fvPatchField, volMesh>> tMpsi = tM() & tpsi();
2954  tM.clear();
2955  tpsi.clear();
2956  return tMpsi;
2957 }
2958 
2959 
2960 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
2961 
2962 template<class Type>
2963 Foam::Ostream& Foam::operator<<(Ostream& os, const fvMatrix<Type>& fvm)
2964 {
2965  os << static_cast<const lduMatrix&>(fvm) << nl
2966  << fvm.dimensions_ << nl
2967  << fvm.source_ << nl
2968  << fvm.internalCoeffs_ << nl
2969  << fvm.boundaryCoeffs_ << endl;
2970 
2972 
2973  return os;
2974 }
2975 
2976 
2977 // * * * * * * * * * * * * * * * * Solvers * * * * * * * * * * * * * * * * * //
2978 
2979 #include "fvMatrixSolve.C"
2980 
2981 // ************************************************************************* //
void mapContributions(label fieldi, const FieldField< Field, Type > &fluxContrib, FieldField< Field, Type > &contrib, bool internal) const
Add internal and boundary contribution to local patches.
Definition: fvMatrix.C:556
Foam::surfaceFields.
void addToInternalField(const labelUList &addr, const Field< Type2 > &pf, Field< Type2 > &intf) const
Add patch contribution to internal field.
Definition: fvMatrix.C:42
faceListList boundary
void update(UPtrList< GeometricField< Type, fvPatchField, volMesh >> &psis)
Update mappings.
tmp< fvMatrix< Type > > correction(const fvMatrix< Type > &)
Return the correction form of the given matrix by subtracting the matrix multiplied by the current fi...
tmp< Field< Type > > faceH(const Field< Type > &) const
virtual bool coupled() const
True if the patch field is coupled.
Definition: fvPatchField.H:250
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
void cmptMax(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
void setValuesFromList(const labelUList &cellLabels, const ListType< Type > &values)
Set solution in given cells to the specified values.
Definition: fvMatrix.C:220
uint8_t direction
Definition: direction.H:48
label faceId(-1)
T & last()
Return reference to the last element of the list.
Definition: UPtrList.H:851
void addBoundaryDiag(scalarField &diag, const direction cmpt) const
Definition: fvMatrix.C:117
void createOrUpdateLduPrimitiveAssembly()
Create or update ldu assembly.
Definition: fvMatrix.C:914
SolverPerformance< Type > solve(faMatrix< Type > &, const dictionary &)
Solve returning the solution statistics given convergence tolerance.
List< cell > cellList
List of cell.
Definition: cellListFwd.H:39
tmp< DimensionedField< typename DimensionedField< Type, GeoMesh >::cmptType, GeoMesh >> cmptAv(const DimensionedField< Type, GeoMesh > &f1)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
UEqn relax()
void relax()
Relax matrix (for steady-state solution).
Definition: fvMatrix.C:1249
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:120
#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 negate()
Inplace negate.
Definition: fvMatrix.C:1585
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:162
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: tmpI.H:244
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:472
void addCmptAvBoundaryDiag(scalarField &diag) const
Definition: fvMatrix.C:145
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
void setReference(const label celli, const Type &value, const bool forceReference=false)
Set reference level for solution.
Definition: fvMatrix.C:1011
void manipulateMatrix(direction cmp)
Manipulate matrix.
Definition: fvMatrix.C:798
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
tmp< GeometricField< Type, fvPatchField, volMesh > > H() const
Return the H operation source.
Definition: fvMatrix.C:1331
A traits class, which is primarily used for primitives.
Definition: pTraits.H:51
void operator-=(const fvMatrix< Type > &)
Definition: fvMatrix.C:1638
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
const dimensionSet dimVol(dimVolume)
Older spelling for dimVolume.
Definition: dimensionSets.H:65
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
Definition: stringOps.C:1186
bool checkImplicit(const label fieldi=0)
Name the implicit assembly addressing.
Definition: fvMatrix.C:315
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1184
Generic GeometricField class.
Definition: areaFieldsFwd.H:50
This boundary condition enforces a cyclic condition between a pair of boundaries, whereby communicati...
Generic dimensioned Type class.
tmp< volScalarField > H1() const
Return H(1)
Definition: fvMatrix.C:1383
Ignore writing from objectRegistry::writeObject()
void subtractFromInternalField(const labelUList &addr, const Field< Type2 > &pf, Field< Type2 > &intf) const
Subtract patch contribution from internal field.
Definition: fvMatrix.C:80
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
DimensionedField< scalar, volMesh > Internal
The internal field type from which this GeometricField is derived.
tmp< scalarField > H1() const
conserve primitiveFieldRef()+
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
tmp< scalarField > D() const
Return the matrix scalar diagonal.
Definition: fvMatrix.C:1279
void operator=(const fvMatrix< Type > &)
Definition: fvMatrix.C:1540
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:164
const dimensionSet dimVolume(pow3(dimLength))
Definition: dimensionSets.H:58
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 > &)
const GeometricField< Type, fvPatchField, volMesh > & psi(const label i=0) const
Return psi.
Definition: fvMatrix.H:485
void setSize(const label n)
Alias for resize()
Definition: List.H:289
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
const cellShapeList & cells
void addFvMatrix(fvMatrix< Type > &matrix)
Add fvMatrix.
Definition: fvMatrix.C:1072
Generic templated field type.
Definition: Field.H:62
void setInterfaces(lduInterfaceFieldPtrsList &, PtrDynList< lduInterfaceField > &newInterfaces)
Set interfaces.
Definition: fvMatrix.C:478
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...
void setReferences(const labelUList &cellLabels, const Type &value, const bool forceReference=false)
Set reference level for solution.
Definition: fvMatrix.C:1027
#define DebugInFunction
Report an information message using Foam::Info.
void checkMethod(const faMatrix< Type > &, const faMatrix< Type > &, const char *)
Definition: faMatrix.C:1032
virtual const lduAddressing & lduAddr() const
Return ldu addressing.
virtual ~fvMatrix()
Destructor.
Definition: fvMatrix.C:464
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition: tmp.H:212
A special matrix type and solver, designed for finite volume solutions of scalar equations. Face addressing is used to make all matrix assembly and solution loops vectorise.
Definition: fvPatchField.H:64
void transferFvMatrixCoeffs()
Transfer lower, upper, diag and source to this fvMatrix.
Definition: fvMatrix.C:821
static const lduMesh & mesh(const lduMesh &mesh0, const PtrList< lduPrimitiveMesh > &otherMeshes, const label meshI)
Select either mesh0 (meshI is 0) or otherMeshes[meshI-1].
errorManip< error > abort(error &err)
Definition: errorManip.H:139
void operator=(const lduMatrix &)
This boundary condition enforces a cyclic condition between a pair of boundaries. ...
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
fvMatrix(const GeometricField< Type, fvPatchField, volMesh > &psi, const dimensionSet &ds)
Construct given a field to solve for.
Definition: fvMatrix.C:352
void operator*=(const scalarField &)
int debug
Static debugging option.
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
An assembly of lduMatrix that is specific inter-region coupling through mapped patches.
A dynamically resizable PtrList with allocation management.
Definition: PtrDynList.H:48
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.
lduPrimitiveMeshAssembly * lduMeshPtr()
Access to lduPrimitiveMeshAssembly.
Definition: fvMatrix.C:888
void operator+=(const fvMatrix< Type > &)
Definition: fvMatrix.C:1600
tmp< Field< Type > > DD() const
Return the matrix Type diagonal.
Definition: fvMatrix.C:1288
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
tmp< volScalarField > A() const
Return the central coefficient.
Definition: fvMatrix.C:1312
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field values.
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Definition: stringOps.C:1170
static bool checking() noexcept
True if dimension checking is enabled (the usual default)
Definition: dimensionSet.H:241
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
virtual const objectRegistry & thisDb() const
Return the object registry.
Definition: lduMesh.C:35
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:79
A List with indirect addressing. Like IndirectList but does not store addressing. ...
Definition: faMatrix.H:56
label cellId
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
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
void correctBoundaryConditions()
Correct boundary field.
messageStream Info
Information stream (stdout output on master, null elsewhere)
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
void addBoundarySource(Field< Type > &source, const bool couples=true) const
Definition: fvMatrix.C:170
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition: tmpI.H:298
const volScalarField & psi
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > flux() const
Return the face-flux field from the matrix.
Definition: fvMatrix.C:1421
void setValues(const labelUList &cellLabels, const Type &value)
Set solution in given cells to the specified value and eliminate the corresponding equations from the...
Definition: fvMatrix.C:978
void boundaryManipulate(typename GeometricField< Type, fvPatchField, volMesh >::Boundary &values)
Manipulate based on a boundary field.
Definition: fvMatrix.C:1266
tmp< Field< Type > > H(const Field< Type > &) const
const dimensionedScalar & D
void operator-=(const lduMatrix &)
void operator+=(const lduMatrix &)
T * ptr() const
Return managed pointer for reuse, or clone() the object reference.
Definition: tmpI.H:265
List< label > labelList
A List of labels.
Definition: List.H:62
void clearOut()
Clear additional addressing.
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
A class for managing temporary objects.
Definition: HashPtrTable.H:50
void setSize(const label n)
Alias for resize()
Definition: UPtrList.H:830
void cmptMin(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
static tmp< GeometricField< scalar, fvPatchField, volMesh > > New(const word &name, const Mesh &mesh, const dimensionSet &dims, const word &patchFieldType=fvPatchField< scalar >::calculatedType())
Return tmp field from name, mesh, dimensions and patch type.
static const word & extrapolatedCalculatedType() noexcept
The type name for extrapolatedCalculated patch fields combines zero-gradient and calculated.
Definition: fvPatchField.H:210
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:171
Request registration (bool: true)
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
void setBounAndInterCoeffs()
Manipulate boundary/internal coeffs for coupling.
Definition: fvMatrix.C:668
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
#define M(I)
This boundary condition enforces a cyclic condition between a pair of boundaries, whereby communicati...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
static const Foam::dimensionedScalar B("", Foam::dimless, 18.678)
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
const dimensionSet & dimensions() const noexcept
Return dimensions.
const dictionary & solverDict() const
Return the solver dictionary taking into account finalIteration.
Definition: fvMatrix.C:1524
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: UPtrList.H:361
#define InfoInFunction
Report an information message using Foam::Info.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:133
void append(autoPtr< T > &ptr)
Move append an element to the end of the list.
Definition: PtrDynList.H:333
void replace(const direction d, const GeometricField< cmptType, PatchField, GeoMesh > &gcf)
Replace specified field component with content from another field.