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-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 "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(),
932  );
933 
934  UPtrList<lduMesh> uMeshPtr(nMatrices());
935 
937  uFieldPtr(nMatrices());
938 
939  for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
940  {
941  const fvMesh& meshi = this->psi(fieldi).mesh();
942  uMeshPtr.set
943  (
944  fieldi,
945  &const_cast<fvMesh&>(meshi)
946  );
947  uFieldPtr.set(fieldi, &this->psi(fieldi));
948  }
949 
950  if (!ptr)
951  {
952  lduPrimitiveMeshAssembly* lduAssemMeshPtr =
953  new lduPrimitiveMeshAssembly(io, uMeshPtr);
954 
955  lduAssemMeshPtr->store();
956  lduAssemMeshPtr->update(uFieldPtr);
957 
958  Info
959  << "Creating lduPrimitiveAssembly: " << lduAssemblyName_ << endl;
960  }
961  else if
962  (
963  psi_.mesh().changing() && !psi_.mesh().upToDatePoints(*ptr)
964  )
965  {
966  // Clear losortPtr_, ownerStartPtr_, losortStartPtr_
967  ptr->lduAddr().clearOut();
968  ptr->update(uFieldPtr);
969  psi_.mesh().setUpToDatePoints(*ptr);
970 
971  Info
972  << "Updating lduPrimitiveAssembly: " << lduAssemblyName_ << endl;
973  }
974  else
975  {
976  Info
977  << "Using lduPrimitiveAssembly: " << lduAssemblyName_ << endl;
978  }
979 }
980 
981 
982 template<class Type>
984 (
985  const labelUList& cellLabels,
986  const Type& value
987 )
988 {
989  this->setValuesFromList(cellLabels, UniformList<Type>(value));
990 }
991 
992 
993 template<class Type>
995 (
996  const labelUList& cellLabels,
997  const UList<Type>& values
998 )
999 {
1000  this->setValuesFromList(cellLabels, values);
1001 }
1002 
1003 
1004 template<class Type>
1006 (
1007  const labelUList& cellLabels,
1009 )
1011  this->setValuesFromList(cellLabels, values);
1012 }
1013 
1014 
1015 template<class Type>
1017 (
1018  const label celli,
1019  const Type& value,
1020  const bool forceReference
1021 )
1022 {
1023  if ((forceReference || psi_.needReference()) && celli >= 0)
1024  {
1025  source()[celli] += diag()[celli]*value;
1026  diag()[celli] += diag()[celli];
1027  }
1028 }
1029 
1030 
1031 template<class Type>
1033 (
1034  const labelUList& cellLabels,
1035  const Type& value,
1036  const bool forceReference
1037 )
1038 {
1039  if (forceReference || psi_.needReference())
1040  {
1041  forAll(cellLabels, celli)
1042  {
1043  const label cellId = cellLabels[celli];
1044  if (cellId >= 0)
1045  {
1046  source()[cellId] += diag()[cellId]*value;
1047  diag()[cellId] += diag()[cellId];
1048  }
1049  }
1050  }
1051 }
1052 
1053 
1054 template<class Type>
1056 (
1057  const labelUList& cellLabels,
1058  const UList<Type>& values,
1059  const bool forceReference
1060 )
1061 {
1062  if (forceReference || psi_.needReference())
1063  {
1064  forAll(cellLabels, celli)
1065  {
1066  const label cellId = cellLabels[celli];
1067  if (cellId >= 0)
1068  {
1069  source()[cellId] += diag()[cellId]*values[celli];
1070  diag()[cellId] += diag()[cellId];
1071  }
1072  }
1073  }
1074 }
1075 
1076 
1077 template<class Type>
1078 void Foam::fvMatrix<Type>::addFvMatrix(fvMatrix& matrix)
1079 {
1080  subMatrices_.append(matrix.clone());
1081  ++nMatrix_;
1082 
1083  if (dimensions_ != matrix.dimensions())
1084  {
1086  << "incompatible dimensions for matrix addition "
1087  << endl << " "
1088  << "[" << dimensions_ << " ] "
1089  << " [" << matrix.dimensions() << " ]"
1090  << abort(FatalError);
1091  }
1092 
1093  for (label fieldi = 0; fieldi < nMatrices(); fieldi++)
1094  {
1095  if (checkImplicit(fieldi))
1096  {
1097  break;
1098  }
1099  }
1101  internalCoeffs_.clear();
1102  boundaryCoeffs_.clear();
1103 }
1104 
1105 
1106 template<class Type>
1107 void Foam::fvMatrix<Type>::relax(const scalar alpha)
1108 {
1109  if (alpha <= 0)
1110  {
1111  return;
1112  }
1113 
1115  << "Relaxing " << psi_.name() << " by " << alpha << endl;
1116 
1117  Field<Type>& S = source();
1118  scalarField& D = diag();
1119 
1120  // Store the current unrelaxed diagonal for use in updating the source
1121  scalarField D0(D);
1122 
1123  // Calculate the sum-mag off-diagonal from the interior faces
1124  scalarField sumOff(D.size(), Zero);
1125  sumMagOffDiag(sumOff);
1126 
1127  // Handle the boundary contributions to the diagonal
1128  forAll(psi_.boundaryField(), patchi)
1129  {
1130  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
1131 
1132  if (ptf.size())
1133  {
1134  const labelUList& pa = lduAddr().patchAddr(patchi);
1135  Field<Type>& iCoeffs = internalCoeffs_[patchi];
1136 
1137  if (ptf.coupled())
1138  {
1139  const Field<Type>& pCoeffs = boundaryCoeffs_[patchi];
1140 
1141  // For coupled boundaries add the diagonal and
1142  // off-diagonal contributions
1143  forAll(pa, face)
1144  {
1145  D[pa[face]] += component(iCoeffs[face], 0);
1146  sumOff[pa[face]] += mag(component(pCoeffs[face], 0));
1147  }
1148  }
1149  else
1150  {
1151  // For non-coupled boundaries add the maximum magnitude diagonal
1152  // contribution to ensure stability
1153  forAll(pa, face)
1154  {
1155  D[pa[face]] += cmptMax(cmptMag(iCoeffs[face]));
1156  }
1157  }
1158  }
1159  }
1160 
1161 
1162  if (debug)
1163  {
1164  // Calculate amount of non-dominance.
1165  label nNon = 0;
1166  scalar maxNon = 0.0;
1167  scalar sumNon = 0.0;
1168  forAll(D, celli)
1169  {
1170  scalar d = (sumOff[celli] - D[celli])/mag(D[celli]);
1171 
1172  if (d > 0)
1173  {
1174  nNon++;
1175  maxNon = max(maxNon, d);
1176  sumNon += d;
1177  }
1178  }
1179 
1180  reduce(nNon, sumOp<label>(), UPstream::msgType(), psi_.mesh().comm());
1181  reduce
1182  (
1183  maxNon,
1184  maxOp<scalar>(),
1186  psi_.mesh().comm()
1187  );
1188  reduce
1189  (
1190  sumNon,
1191  sumOp<scalar>(),
1193  psi_.mesh().comm()
1194  );
1195  sumNon /= returnReduce
1196  (
1197  D.size(),
1198  sumOp<label>(),
1200  psi_.mesh().comm()
1201  );
1202 
1204  << "Matrix dominance test for " << psi_.name() << nl
1205  << " number of non-dominant cells : " << nNon << nl
1206  << " maximum relative non-dominance : " << maxNon << nl
1207  << " average relative non-dominance : " << sumNon << nl
1208  << endl;
1209  }
1210 
1211 
1212  // Ensure the matrix is diagonally dominant...
1213  // Assumes that the central coefficient is positive and ensures it is
1214  forAll(D, celli)
1215  {
1216  D[celli] = max(mag(D[celli]), sumOff[celli]);
1217  }
1218 
1219  // ... then relax
1220  D /= alpha;
1221 
1222  // Now remove the diagonal contribution from coupled boundaries
1223  forAll(psi_.boundaryField(), patchi)
1224  {
1225  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
1226 
1227  if (ptf.size())
1228  {
1229  const labelUList& pa = lduAddr().patchAddr(patchi);
1230  Field<Type>& iCoeffs = internalCoeffs_[patchi];
1231 
1232  if (ptf.coupled())
1233  {
1234  forAll(pa, face)
1235  {
1236  D[pa[face]] -= component(iCoeffs[face], 0);
1237  }
1238  }
1239  else
1240  {
1241  forAll(pa, face)
1242  {
1243  D[pa[face]] -= cmptMin(iCoeffs[face]);
1244  }
1245  }
1246  }
1247  }
1249  // Finally add the relaxation contribution to the source.
1250  S += (D - D0)*psi_.primitiveField();
1251 }
1252 
1253 
1254 template<class Type>
1256 {
1257  word name = psi_.select
1258  (
1259  psi_.mesh().data::template getOrDefault<bool>
1260  ("finalIteration", false)
1261  );
1262 
1263  if (psi_.mesh().relaxEquation(name))
1264  {
1265  relax(psi_.mesh().equationRelaxationFactor(name));
1266  }
1267 }
1268 
1269 
1270 template<class Type>
1272 (
1273  typename GeometricField<Type, fvPatchField, volMesh>::
1274  Boundary& bFields
1275 )
1276 {
1277  forAll(bFields, patchi)
1278  {
1279  bFields[patchi].manipulateMatrix(*this);
1280  }
1281 }
1282 
1283 
1284 template<class Type>
1286 {
1288  addCmptAvBoundaryDiag(tdiag.ref());
1289  return tdiag;
1290 }
1291 
1292 
1293 template<class Type>
1295 {
1297 
1298  forAll(psi_.boundaryField(), patchi)
1299  {
1300  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
1301 
1302  if (!ptf.coupled() && ptf.size())
1303  {
1304  addToInternalField
1305  (
1306  lduAddr().patchAddr(patchi),
1307  internalCoeffs_[patchi],
1308  tdiag.ref()
1309  );
1310  }
1311  }
1312 
1313  return tdiag;
1314 }
1315 
1316 
1317 template<class Type>
1319 {
1320  tmp<volScalarField> tAphi
1321  (
1322  new volScalarField
1323  (
1324  IOobject
1325  (
1326  "A("+psi_.name()+')',
1327  psi_.instance(),
1328  psi_.mesh(),
1331  ),
1332  psi_.mesh(),
1333  dimensions_/psi_.dimensions()/dimVol,
1334  extrapolatedCalculatedFvPatchScalarField::typeName
1335  )
1336  );
1337 
1338  tAphi.ref().primitiveFieldRef() = D()/psi_.mesh().V();
1339  tAphi.ref().correctBoundaryConditions();
1341  return tAphi;
1342 }
1343 
1344 
1345 template<class Type>
1348 {
1350  (
1352  (
1353  IOobject
1354  (
1355  "H("+psi_.name()+')',
1356  psi_.instance(),
1357  psi_.mesh(),
1360  ),
1361  psi_.mesh(),
1362  dimensions_/dimVol,
1363  extrapolatedCalculatedFvPatchScalarField::typeName
1364  )
1365  );
1367 
1368  // Loop over field components
1369  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
1370  {
1371  scalarField psiCmpt(psi_.primitiveField().component(cmpt));
1372 
1373  scalarField boundaryDiagCmpt(psi_.size(), Zero);
1374  addBoundaryDiag(boundaryDiagCmpt, cmpt);
1375  boundaryDiagCmpt.negate();
1376  addCmptAvBoundaryDiag(boundaryDiagCmpt);
1377 
1378  Hphi.primitiveFieldRef().replace(cmpt, boundaryDiagCmpt*psiCmpt);
1379  }
1380 
1381  Hphi.primitiveFieldRef() += lduMatrix::H(psi_.primitiveField()) + source_;
1382  addBoundarySource(Hphi.primitiveFieldRef());
1383 
1384  Hphi.primitiveFieldRef() /= psi_.mesh().V();
1386 
1387  typename Type::labelType validComponents
1388  (
1389  psi_.mesh().template validComponents<Type>()
1390  );
1391 
1392  for (direction cmpt=0; cmpt<Type::nComponents; cmpt++)
1393  {
1394  if (validComponents[cmpt] == -1)
1395  {
1396  Hphi.replace
1397  (
1398  cmpt,
1400  );
1401  }
1402  }
1403 
1404  return tHphi;
1405 }
1406 
1407 
1408 template<class Type>
1410 {
1411  tmp<volScalarField> tH1
1412  (
1413  new volScalarField
1414  (
1415  IOobject
1416  (
1417  "H(1)",
1418  psi_.instance(),
1419  psi_.mesh(),
1422  ),
1423  psi_.mesh(),
1424  dimensions_/(dimVol*psi_.dimensions()),
1425  extrapolatedCalculatedFvPatchScalarField::typeName
1426  )
1427  );
1428  volScalarField& H1_ = tH1.ref();
1429 
1430  H1_.primitiveFieldRef() = lduMatrix::H1();
1431 
1432  forAll(psi_.boundaryField(), patchi)
1433  {
1434  const fvPatchField<Type>& ptf = psi_.boundaryField()[patchi];
1435 
1436  if (ptf.coupled() && ptf.size())
1437  {
1438  addToInternalField
1439  (
1440  lduAddr().patchAddr(patchi),
1441  boundaryCoeffs_[patchi].component(0),
1442  H1_
1443  );
1444  }
1445  }
1446 
1447  H1_.primitiveFieldRef() /= psi_.mesh().V();
1448  H1_.correctBoundaryConditions();
1449 
1450  return tH1;
1452 
1453 
1454 
1455 template<class Type>
1458 flux() const
1459 {
1460  if (!psi_.mesh().fluxRequired(psi_.name()))
1461  {
1463  << "flux requested but " << psi_.name()
1464  << " not specified in the fluxRequired sub-dictionary"
1465  " of fvSchemes."
1466  << abort(FatalError);
1467  }
1468 
1469  if (nMatrices() > 1)
1470  {
1472  << "Flux requested but " << psi_.name()
1473  << " can't handle multiple fvMatrix."
1474  << abort(FatalError);
1475  }
1476 
1477  // construct GeometricField<Type, fvsPatchField, surfaceMesh>
1478  tmp<GeometricField<Type, fvsPatchField, surfaceMesh>> tfieldFlux
1479  (
1480  new GeometricField<Type, fvsPatchField, surfaceMesh>
1481  (
1482  IOobject
1483  (
1484  "flux("+psi_.name()+')',
1485  psi_.instance(),
1486  psi_.mesh(),
1489  ),
1490  psi_.mesh(),
1491  dimensions()
1492  )
1493  );
1494  GeometricField<Type, fvsPatchField, surfaceMesh>& fieldFlux =
1495  tfieldFlux.ref();
1496 
1497  fieldFlux.setOriented();
1498 
1499  for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
1500  {
1501  fieldFlux.primitiveFieldRef().replace
1502  (
1503  cmpt,
1504  lduMatrix::faceH(psi_.primitiveField().component(cmpt))
1505  );
1506  }
1507 
1508  FieldField<Field, Type> InternalContrib = internalCoeffs_;
1509 
1510  label fieldi = 0;
1511  if (!useImplicit_)
1512  {
1513  forAll(InternalContrib, patchi)
1514  {
1515  InternalContrib[patchi] =
1516  cmptMultiply
1517  (
1518  InternalContrib[patchi],
1519  psi_.boundaryField()[patchi].patchInternalField()
1520  );
1521  }
1522  }
1523  else
1524  {
1525  FieldField<Field, Type> fluxInternalContrib(internalCoeffs_);
1526 
1527  mapContributions(fieldi, fluxInternalContrib, InternalContrib, true);
1528  }
1529 
1530  FieldField<Field, Type> NeighbourContrib = boundaryCoeffs_;
1531 
1532  if (!useImplicit_)
1533  {
1534  forAll(NeighbourContrib, patchi)
1535  {
1536  if (psi_.boundaryField()[patchi].coupled())
1537  {
1538  NeighbourContrib[patchi] =
1539  cmptMultiply
1540  (
1541  NeighbourContrib[patchi],
1542  psi_.boundaryField()[patchi].patchNeighbourField()
1543  );
1544  }
1545  }
1546  }
1547  else
1548  {
1549  FieldField<Field, Type> fluxBoundaryContrib(boundaryCoeffs_);
1550 
1551  mapContributions(fieldi, fluxBoundaryContrib, NeighbourContrib, false);
1552  }
1553 
1554  typename GeometricField<Type, fvsPatchField, surfaceMesh>::
1555  Boundary& ffbf = fieldFlux.boundaryFieldRef();
1556 
1557  forAll(ffbf, patchi)
1558  {
1559  ffbf[patchi] = InternalContrib[patchi] - NeighbourContrib[patchi];
1560  //DebugVar(gSum(ffbf[patchi]))
1561  }
1562 
1563  if (faceFluxCorrectionPtr_)
1564  {
1565  fieldFlux += *faceFluxCorrectionPtr_;
1566  }
1567 
1568  return tfieldFlux;
1569 }
1570 
1571 
1572 template<class Type>
1574 {
1575  return psi_.mesh().solverDict
1576  (
1577  psi_.select
1578  (
1579  psi_.mesh().data::template getOrDefault<bool>
1580  ("finalIteration", false)
1581  )
1582  );
1583 }
1584 
1585 
1586 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1587 
1588 template<class Type>
1590 {
1591  if (this == &fvmv)
1592  {
1593  return; // Self-assignment is a no-op
1594  }
1595 
1596  if (&psi_ != &(fvmv.psi_))
1597  {
1599  << "different fields"
1600  << abort(FatalError);
1601  }
1602 
1603  dimensions_ = fvmv.dimensions_;
1604  lduMatrix::operator=(fvmv);
1605  source_ = fvmv.source_;
1606  internalCoeffs_ = fvmv.internalCoeffs_;
1607  boundaryCoeffs_ = fvmv.boundaryCoeffs_;
1608 
1609  if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
1610  {
1611  *faceFluxCorrectionPtr_ = *fvmv.faceFluxCorrectionPtr_;
1612  }
1613  else if (fvmv.faceFluxCorrectionPtr_)
1614  {
1615  faceFluxCorrectionPtr_ =
1616  new GeometricField<Type, fvsPatchField, surfaceMesh>
1617  (*fvmv.faceFluxCorrectionPtr_);
1618  }
1620  useImplicit_ = fvmv.useImplicit_;
1621  lduAssemblyName_ = fvmv.lduAssemblyName_;
1622 }
1623 
1624 
1625 template<class Type>
1628  operator=(tfvmv());
1629  tfvmv.clear();
1630 }
1631 
1632 
1633 template<class Type>
1635 {
1637  source_.negate();
1638  internalCoeffs_.negate();
1639  boundaryCoeffs_.negate();
1640 
1641  if (faceFluxCorrectionPtr_)
1642  {
1643  faceFluxCorrectionPtr_->negate();
1644  }
1645 }
1646 
1647 
1648 template<class Type>
1649 void Foam::fvMatrix<Type>::operator+=(const fvMatrix<Type>& fvmv)
1650 {
1651  checkMethod(*this, fvmv, "+=");
1652 
1653  dimensions_ += fvmv.dimensions_;
1654  lduMatrix::operator+=(fvmv);
1655  source_ += fvmv.source_;
1656  internalCoeffs_ += fvmv.internalCoeffs_;
1657  boundaryCoeffs_ += fvmv.boundaryCoeffs_;
1658 
1659  useImplicit_ = fvmv.useImplicit_;
1660  lduAssemblyName_ = fvmv.lduAssemblyName_;
1661  nMatrix_ = fvmv.nMatrix_;
1662 
1663  if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
1664  {
1665  *faceFluxCorrectionPtr_ += *fvmv.faceFluxCorrectionPtr_;
1666  }
1667  else if (fvmv.faceFluxCorrectionPtr_)
1668  {
1669  faceFluxCorrectionPtr_ = new
1670  GeometricField<Type, fvsPatchField, surfaceMesh>
1671  (
1672  *fvmv.faceFluxCorrectionPtr_
1673  );
1674  }
1675 }
1676 
1677 
1678 template<class Type>
1679 void Foam::fvMatrix<Type>::operator+=(const tmp<fvMatrix<Type>>& tfvmv)
1681  operator+=(tfvmv());
1682  tfvmv.clear();
1683 }
1684 
1685 
1686 template<class Type>
1688 {
1689  checkMethod(*this, fvmv, "-=");
1690 
1691  dimensions_ -= fvmv.dimensions_;
1692  lduMatrix::operator-=(fvmv);
1693  source_ -= fvmv.source_;
1694  internalCoeffs_ -= fvmv.internalCoeffs_;
1695  boundaryCoeffs_ -= fvmv.boundaryCoeffs_;
1696 
1697  useImplicit_ = fvmv.useImplicit_;
1698  lduAssemblyName_ = fvmv.lduAssemblyName_;
1699  nMatrix_ = fvmv.nMatrix_;
1700 
1701  if (faceFluxCorrectionPtr_ && fvmv.faceFluxCorrectionPtr_)
1702  {
1703  *faceFluxCorrectionPtr_ -= *fvmv.faceFluxCorrectionPtr_;
1704  }
1705  else if (fvmv.faceFluxCorrectionPtr_)
1706  {
1707  faceFluxCorrectionPtr_ =
1709  (-*fvmv.faceFluxCorrectionPtr_);
1710  }
1711 }
1712 
1713 
1714 template<class Type>
1715 void Foam::fvMatrix<Type>::operator-=(const tmp<fvMatrix<Type>>& tfvmv)
1716 {
1717  operator-=(tfvmv());
1718  tfvmv.clear();
1719 }
1720 
1721 
1722 template<class Type>
1724 (
1726 )
1727 {
1728  checkMethod(*this, su, "+=");
1729  source() -= su.mesh().V()*su.field();
1730 }
1731 
1732 
1733 template<class Type>
1735 (
1737 )
1738 {
1739  operator+=(tsu());
1740  tsu.clear();
1741 }
1742 
1743 
1744 template<class Type>
1746 (
1748 )
1749 {
1750  operator+=(tsu());
1751  tsu.clear();
1752 }
1753 
1754 
1755 template<class Type>
1757 (
1759 )
1760 {
1761  checkMethod(*this, su, "-=");
1762  source() += su.mesh().V()*su.field();
1763 }
1764 
1765 
1766 template<class Type>
1768 (
1770 )
1771 {
1772  operator-=(tsu());
1773  tsu.clear();
1774 }
1775 
1776 
1777 template<class Type>
1779 (
1781 )
1782 {
1783  operator-=(tsu());
1784  tsu.clear();
1785 }
1786 
1787 
1788 template<class Type>
1790 (
1791  const dimensioned<Type>& su
1792 )
1794  source() -= psi().mesh().V()*su;
1795 }
1796 
1797 
1798 template<class Type>
1800 (
1801  const dimensioned<Type>& su
1803 {
1804  source() += psi().mesh().V()*su;
1805 }
1806 
1808 template<class Type>
1810 {}
1811 
1812 
1813 template<class Type>
1815 {}
1816 
1817 
1818 template<class Type>
1820 (
1821  const volScalarField::Internal& dsf
1822 )
1823 {
1824  dimensions_ *= dsf.dimensions();
1825  lduMatrix::operator*=(dsf.field());
1826  source_ *= dsf.field();
1827 
1828  forAll(boundaryCoeffs_, patchi)
1829  {
1830  scalarField pisf
1831  (
1832  dsf.mesh().boundary()[patchi].patchInternalField(dsf.field())
1833  );
1834 
1835  internalCoeffs_[patchi] *= pisf;
1836  boundaryCoeffs_[patchi] *= pisf;
1837  }
1838 
1839  if (faceFluxCorrectionPtr_)
1840  {
1842  << "cannot scale a matrix containing a faceFluxCorrection"
1844  }
1845 }
1846 
1847 
1848 template<class Type>
1850 (
1851  const tmp<volScalarField::Internal>& tfld
1852 )
1853 {
1854  operator*=(tfld());
1855  tfld.clear();
1856 }
1857 
1858 
1859 template<class Type>
1861 (
1862  const tmp<volScalarField>& tfld
1863 )
1864 {
1865  operator*=(tfld());
1866  tfld.clear();
1867 }
1868 
1869 
1870 template<class Type>
1872 (
1873  const dimensioned<scalar>& ds
1874 )
1875 {
1876  dimensions_ *= ds.dimensions();
1877  lduMatrix::operator*=(ds.value());
1878  source_ *= ds.value();
1879  internalCoeffs_ *= ds.value();
1880  boundaryCoeffs_ *= ds.value();
1881 
1882  if (faceFluxCorrectionPtr_)
1883  {
1884  *faceFluxCorrectionPtr_ *= ds.value();
1885  }
1887 
1888 
1889 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
1890 
1891 template<class Type>
1892 void Foam::checkMethod
1893 (
1894  const fvMatrix<Type>& mat1,
1895  const fvMatrix<Type>& mat2,
1896  const char* op
1897 )
1898 {
1899  if (&mat1.psi() != &mat2.psi())
1900  {
1902  << "Incompatible fields for operation\n "
1903  << "[" << mat1.psi().name() << "] "
1904  << op
1905  << " [" << mat2.psi().name() << "]"
1906  << abort(FatalError);
1907  }
1908 
1909  if
1910  (
1912  && mat1.dimensions() != mat2.dimensions()
1913  )
1914  {
1916  << "Incompatible dimensions for operation\n "
1917  << "[" << mat1.psi().name() << mat1.dimensions()/dimVolume << " ] "
1918  << op
1919  << " [" << mat2.psi().name() << mat2.dimensions()/dimVolume << " ]"
1921  }
1922 }
1923 
1924 
1925 template<class Type>
1926 void Foam::checkMethod
1927 (
1928  const fvMatrix<Type>& mat,
1929  const DimensionedField<Type, volMesh>& fld,
1930  const char* op
1931 )
1932 {
1933  if
1934  (
1936  && mat.dimensions()/dimVolume != fld.dimensions()
1937  )
1938  {
1940  << "Incompatible dimensions for operation\n "
1941  << "[" << mat.psi().name() << mat.dimensions()/dimVolume << " ] "
1942  << op
1943  << " [" << fld.name() << fld.dimensions() << " ]"
1945  }
1946 }
1947 
1948 
1949 template<class Type>
1950 void Foam::checkMethod
1951 (
1952  const fvMatrix<Type>& mat,
1953  const dimensioned<Type>& dt,
1954  const char* op
1955 )
1956 {
1957  if
1958  (
1960  && mat.dimensions()/dimVolume != dt.dimensions()
1961  )
1962  {
1964  << "Incompatible dimensions for operation\n "
1965  << "[" << mat.psi().name() << mat.dimensions()/dimVolume << " ] "
1966  << op
1967  << " [" << dt.name() << dt.dimensions() << " ]"
1968  << abort(FatalError);
1969  }
1970 }
1971 
1972 
1973 template<class Type>
1975 (
1976  fvMatrix<Type>& fvm,
1977  const dictionary& solverControls
1978 )
1979 {
1980  return fvm.solve(solverControls);
1981 }
1982 
1983 template<class Type>
1985 (
1986  const tmp<fvMatrix<Type>>& tmat,
1987  const dictionary& solverControls
1988 )
1989 {
1990  SolverPerformance<Type> solverPerf(tmat.constCast().solve(solverControls));
1991 
1992  tmat.clear();
1993 
1994  return solverPerf;
1995 }
1996 
1997 
1998 template<class Type>
1999 Foam::SolverPerformance<Type> Foam::solve(fvMatrix<Type>& fvm)
2000 {
2001  return fvm.solve();
2002 }
2003 
2004 template<class Type>
2005 Foam::SolverPerformance<Type> Foam::solve(const tmp<fvMatrix<Type>>& tmat)
2006 {
2007  SolverPerformance<Type> solverPerf(tmat.constCast().solve());
2008 
2009  tmat.clear();
2010 
2011  return solverPerf;
2012 }
2013 
2014 
2015 template<class Type>
2017 (
2018  const fvMatrix<Type>& A
2019 )
2020 {
2021  tmp<Foam::fvMatrix<Type>> tAcorr = A - (A & A.psi());
2022 
2023  // Delete the faceFluxCorrection from the correction matrix
2024  // as it does not have a clear meaning or purpose
2025  deleteDemandDrivenData(tAcorr.ref().faceFluxCorrectionPtr());
2026 
2027  return tAcorr;
2028 }
2029 
2030 
2031 template<class Type>
2033 (
2034  const tmp<fvMatrix<Type>>& tA
2035 )
2036 {
2037  tmp<Foam::fvMatrix<Type>> tAcorr = tA - (tA() & tA().psi());
2038 
2039  // Delete the faceFluxCorrection from the correction matrix
2040  // as it does not have a clear meaning or purpose
2041  deleteDemandDrivenData(tAcorr.ref().faceFluxCorrectionPtr());
2042 
2043  return tAcorr;
2044 }
2045 
2046 
2047 // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
2048 
2049 template<class Type>
2050 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2051 (
2052  const fvMatrix<Type>& A,
2053  const fvMatrix<Type>& B
2054 )
2055 {
2056  checkMethod(A, B, "==");
2057  return (A - B);
2058 }
2059 
2060 template<class Type>
2061 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2062 (
2063  const tmp<fvMatrix<Type>>& tA,
2064  const fvMatrix<Type>& B
2065 )
2066 {
2067  checkMethod(tA(), B, "==");
2068  return (tA - B);
2069 }
2070 
2071 template<class Type>
2072 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2073 (
2074  const fvMatrix<Type>& A,
2075  const tmp<fvMatrix<Type>>& tB
2076 )
2077 {
2078  checkMethod(A, tB(), "==");
2079  return (A - tB);
2080 }
2081 
2082 template<class Type>
2083 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2084 (
2085  const tmp<fvMatrix<Type>>& tA,
2086  const tmp<fvMatrix<Type>>& tB
2087 )
2088 {
2089  checkMethod(tA(), tB(), "==");
2090  return (tA - tB);
2091 }
2092 
2093 template<class Type>
2094 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2095 (
2096  const fvMatrix<Type>& A,
2097  const DimensionedField<Type, volMesh>& su
2098 )
2099 {
2100  checkMethod(A, su, "==");
2101  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2102  tC.ref().source() += su.mesh().V()*su.field();
2103  return tC;
2104 }
2105 
2106 template<class Type>
2107 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2108 (
2109  const fvMatrix<Type>& A,
2110  const tmp<DimensionedField<Type, volMesh>>& tsu
2111 )
2112 {
2113  checkMethod(A, tsu(), "==");
2114  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2115  tC.ref().source() += tsu().mesh().V()*tsu().field();
2116  tsu.clear();
2117  return tC;
2118 }
2119 
2120 template<class Type>
2121 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2122 (
2123  const fvMatrix<Type>& A,
2124  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2125 )
2126 {
2127  checkMethod(A, tsu(), "==");
2128  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2129  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2130  tsu.clear();
2131  return tC;
2132 }
2133 
2134 template<class Type>
2135 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2136 (
2137  const tmp<fvMatrix<Type>>& tA,
2138  const DimensionedField<Type, volMesh>& su
2139 )
2140 {
2141  checkMethod(tA(), su, "==");
2142  tmp<fvMatrix<Type>> tC(tA.ptr());
2143  tC.ref().source() += su.mesh().V()*su.field();
2144  return tC;
2145 }
2146 
2147 template<class Type>
2148 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2149 (
2150  const tmp<fvMatrix<Type>>& tA,
2151  const tmp<DimensionedField<Type, volMesh>>& tsu
2152 )
2153 {
2154  checkMethod(tA(), tsu(), "==");
2155  tmp<fvMatrix<Type>> tC(tA.ptr());
2156  tC.ref().source() += tsu().mesh().V()*tsu().field();
2157  tsu.clear();
2158  return tC;
2159 }
2160 
2161 template<class Type>
2162 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2163 (
2164  const tmp<fvMatrix<Type>>& tA,
2165  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2166 )
2167 {
2168  checkMethod(tA(), tsu(), "==");
2169  tmp<fvMatrix<Type>> tC(tA.ptr());
2170  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2171  tsu.clear();
2172  return tC;
2173 }
2174 
2175 template<class Type>
2176 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2177 (
2178  const fvMatrix<Type>& A,
2179  const dimensioned<Type>& su
2180 )
2181 {
2182  checkMethod(A, su, "==");
2183  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2184  tC.ref().source() += A.psi().mesh().V()*su.value();
2185  return tC;
2186 }
2187 
2188 template<class Type>
2189 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2190 (
2191  const tmp<fvMatrix<Type>>& tA,
2192  const dimensioned<Type>& su
2193 )
2194 {
2195  checkMethod(tA(), su, "==");
2196  tmp<fvMatrix<Type>> tC(tA.ptr());
2197  tC.ref().source() += tC().psi().mesh().V()*su.value();
2198  return tC;
2199 }
2200 
2201 template<class Type>
2202 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2203 (
2204  const fvMatrix<Type>& A,
2205  const Foam::zero
2206 )
2207 {
2208  return A;
2209 }
2210 
2211 
2212 template<class Type>
2213 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
2214 (
2215  const tmp<fvMatrix<Type>>& tA,
2216  const Foam::zero
2217 )
2218 {
2219  return tA;
2220 }
2221 
2222 
2223 template<class Type>
2224 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2225 (
2226  const fvMatrix<Type>& A
2227 )
2228 {
2229  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2230  tC.ref().negate();
2231  return tC;
2232 }
2233 
2234 template<class Type>
2235 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2236 (
2237  const tmp<fvMatrix<Type>>& tA
2238 )
2239 {
2240  tmp<fvMatrix<Type>> tC(tA.ptr());
2241  tC.ref().negate();
2242  return tC;
2243 }
2244 
2245 
2246 template<class Type>
2247 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2248 (
2249  const fvMatrix<Type>& A,
2250  const fvMatrix<Type>& B
2251 )
2252 {
2253  checkMethod(A, B, "+");
2254  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2255  tC.ref() += B;
2256  return tC;
2257 }
2258 
2259 template<class Type>
2260 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2261 (
2262  const tmp<fvMatrix<Type>>& tA,
2263  const fvMatrix<Type>& B
2264 )
2265 {
2266  checkMethod(tA(), B, "+");
2267  tmp<fvMatrix<Type>> tC(tA.ptr());
2268  tC.ref() += B;
2269  return tC;
2270 }
2271 
2272 template<class Type>
2273 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2274 (
2275  const fvMatrix<Type>& A,
2276  const tmp<fvMatrix<Type>>& tB
2277 )
2278 {
2279  checkMethod(A, tB(), "+");
2280  tmp<fvMatrix<Type>> tC(tB.ptr());
2281  tC.ref() += A;
2282  return tC;
2283 }
2284 
2285 template<class Type>
2286 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2287 (
2288  const tmp<fvMatrix<Type>>& tA,
2289  const tmp<fvMatrix<Type>>& tB
2290 )
2291 {
2292  checkMethod(tA(), tB(), "+");
2293  tmp<fvMatrix<Type>> tC(tA.ptr());
2294  tC.ref() += tB();
2295  tB.clear();
2296  return tC;
2297 }
2298 
2299 template<class Type>
2300 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2301 (
2302  const fvMatrix<Type>& A,
2303  const DimensionedField<Type, volMesh>& su
2304 )
2305 {
2306  checkMethod(A, su, "+");
2307  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2308  tC.ref().source() -= su.mesh().V()*su.field();
2309  return tC;
2310 }
2311 
2312 template<class Type>
2313 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2314 (
2315  const fvMatrix<Type>& A,
2316  const tmp<DimensionedField<Type, volMesh>>& tsu
2317 )
2318 {
2319  checkMethod(A, tsu(), "+");
2320  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2321  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2322  tsu.clear();
2323  return tC;
2324 }
2325 
2326 template<class Type>
2327 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2328 (
2329  const fvMatrix<Type>& A,
2330  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2331 )
2332 {
2333  checkMethod(A, tsu(), "+");
2334  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2335  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2336  tsu.clear();
2337  return tC;
2338 }
2339 
2340 template<class Type>
2341 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2342 (
2343  const tmp<fvMatrix<Type>>& tA,
2344  const DimensionedField<Type, volMesh>& su
2345 )
2346 {
2347  checkMethod(tA(), su, "+");
2348  tmp<fvMatrix<Type>> tC(tA.ptr());
2349  tC.ref().source() -= su.mesh().V()*su.field();
2350  return tC;
2351 }
2352 
2353 template<class Type>
2354 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2355 (
2356  const tmp<fvMatrix<Type>>& tA,
2357  const tmp<DimensionedField<Type, volMesh>>& tsu
2358 )
2359 {
2360  checkMethod(tA(), tsu(), "+");
2361  tmp<fvMatrix<Type>> tC(tA.ptr());
2362  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2363  tsu.clear();
2364  return tC;
2365 }
2366 
2367 template<class Type>
2368 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2369 (
2370  const tmp<fvMatrix<Type>>& tA,
2371  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2372 )
2373 {
2374  checkMethod(tA(), tsu(), "+");
2375  tmp<fvMatrix<Type>> tC(tA.ptr());
2376  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2377  tsu.clear();
2378  return tC;
2379 }
2380 
2381 template<class Type>
2382 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2383 (
2384  const DimensionedField<Type, volMesh>& su,
2385  const fvMatrix<Type>& A
2386 )
2387 {
2388  checkMethod(A, su, "+");
2389  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2390  tC.ref().source() -= su.mesh().V()*su.field();
2391  return tC;
2392 }
2393 
2394 template<class Type>
2395 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2396 (
2397  const tmp<DimensionedField<Type, volMesh>>& tsu,
2398  const fvMatrix<Type>& A
2399 )
2400 {
2401  checkMethod(A, tsu(), "+");
2402  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2403  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2404  tsu.clear();
2405  return tC;
2406 }
2407 
2408 template<class Type>
2409 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2410 (
2411  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu,
2412  const fvMatrix<Type>& A
2413 )
2414 {
2415  checkMethod(A, tsu(), "+");
2416  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2417  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2418  tsu.clear();
2419  return tC;
2420 }
2421 
2422 template<class Type>
2423 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2424 (
2425  const DimensionedField<Type, volMesh>& su,
2426  const tmp<fvMatrix<Type>>& tA
2427 )
2428 {
2429  checkMethod(tA(), su, "+");
2430  tmp<fvMatrix<Type>> tC(tA.ptr());
2431  tC.ref().source() -= su.mesh().V()*su.field();
2432  return tC;
2433 }
2434 
2435 template<class Type>
2436 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2437 (
2438  const tmp<DimensionedField<Type, volMesh>>& tsu,
2439  const tmp<fvMatrix<Type>>& tA
2440 )
2441 {
2442  checkMethod(tA(), tsu(), "+");
2443  tmp<fvMatrix<Type>> tC(tA.ptr());
2444  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2445  tsu.clear();
2446  return tC;
2447 }
2448 
2449 template<class Type>
2450 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2451 (
2452  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu,
2453  const tmp<fvMatrix<Type>>& tA
2454 )
2455 {
2456  checkMethod(tA(), tsu(), "+");
2457  tmp<fvMatrix<Type>> tC(tA.ptr());
2458  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2459  tsu.clear();
2460  return tC;
2461 }
2462 
2463 
2464 template<class Type>
2465 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2466 (
2467  const fvMatrix<Type>& A,
2468  const fvMatrix<Type>& B
2469 )
2470 {
2471  checkMethod(A, B, "-");
2472  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2473  tC.ref() -= B;
2474  return tC;
2475 }
2476 
2477 template<class Type>
2478 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2479 (
2480  const tmp<fvMatrix<Type>>& tA,
2481  const fvMatrix<Type>& B
2482 )
2483 {
2484  checkMethod(tA(), B, "-");
2485  tmp<fvMatrix<Type>> tC(tA.ptr());
2486  tC.ref() -= B;
2487  return tC;
2488 }
2489 
2490 template<class Type>
2491 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2492 (
2493  const fvMatrix<Type>& A,
2494  const tmp<fvMatrix<Type>>& tB
2495 )
2496 {
2497  checkMethod(A, tB(), "-");
2498  tmp<fvMatrix<Type>> tC(tB.ptr());
2499  tC.ref() -= A;
2500  tC.ref().negate();
2501  return tC;
2502 }
2503 
2504 template<class Type>
2505 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2506 (
2507  const tmp<fvMatrix<Type>>& tA,
2508  const tmp<fvMatrix<Type>>& tB
2509 )
2510 {
2511  checkMethod(tA(), tB(), "-");
2512  tmp<fvMatrix<Type>> tC(tA.ptr());
2513  tC.ref() -= tB();
2514  tB.clear();
2515  return tC;
2516 }
2517 
2518 template<class Type>
2519 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2520 (
2521  const fvMatrix<Type>& A,
2522  const DimensionedField<Type, volMesh>& su
2523 )
2524 {
2525  checkMethod(A, su, "-");
2526  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2527  tC.ref().source() += su.mesh().V()*su.field();
2528  return tC;
2529 }
2530 
2531 template<class Type>
2532 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2533 (
2534  const fvMatrix<Type>& A,
2535  const tmp<DimensionedField<Type, volMesh>>& tsu
2536 )
2537 {
2538  checkMethod(A, tsu(), "-");
2539  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2540  tC.ref().source() += tsu().mesh().V()*tsu().field();
2541  tsu.clear();
2542  return tC;
2543 }
2544 
2545 template<class Type>
2546 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2547 (
2548  const fvMatrix<Type>& A,
2549  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2550 )
2551 {
2552  checkMethod(A, tsu(), "-");
2553  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2554  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2555  tsu.clear();
2556  return tC;
2557 }
2558 
2559 template<class Type>
2560 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2561 (
2562  const tmp<fvMatrix<Type>>& tA,
2563  const DimensionedField<Type, volMesh>& su
2564 )
2565 {
2566  checkMethod(tA(), su, "-");
2567  tmp<fvMatrix<Type>> tC(tA.ptr());
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<fvMatrix<Type>>& tA,
2576  const tmp<DimensionedField<Type, volMesh>>& tsu
2577 )
2578 {
2579  checkMethod(tA(), tsu(), "-");
2580  tmp<fvMatrix<Type>> tC(tA.ptr());
2581  tC.ref().source() += tsu().mesh().V()*tsu().field();
2582  tsu.clear();
2583  return tC;
2584 }
2585 
2586 template<class Type>
2587 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2588 (
2589  const tmp<fvMatrix<Type>>& tA,
2590  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu
2591 )
2592 {
2593  checkMethod(tA(), tsu(), "-");
2594  tmp<fvMatrix<Type>> tC(tA.ptr());
2595  tC.ref().source() += tsu().mesh().V()*tsu().primitiveField();
2596  tsu.clear();
2597  return tC;
2598 }
2599 
2600 template<class Type>
2601 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2602 (
2603  const DimensionedField<Type, volMesh>& su,
2604  const fvMatrix<Type>& A
2605 )
2606 {
2607  checkMethod(A, su, "-");
2608  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2609  tC.ref().negate();
2610  tC.ref().source() -= su.mesh().V()*su.field();
2611  return tC;
2612 }
2613 
2614 template<class Type>
2615 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2616 (
2617  const tmp<DimensionedField<Type, volMesh>>& tsu,
2618  const fvMatrix<Type>& A
2619 )
2620 {
2621  checkMethod(A, tsu(), "-");
2622  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2623  tC.ref().negate();
2624  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2625  tsu.clear();
2626  return tC;
2627 }
2628 
2629 template<class Type>
2630 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2631 (
2632  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu,
2633  const fvMatrix<Type>& A
2634 )
2635 {
2636  checkMethod(A, tsu(), "-");
2637  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2638  tC.ref().negate();
2639  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2640  tsu.clear();
2641  return tC;
2642 }
2643 
2644 template<class Type>
2645 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2646 (
2647  const DimensionedField<Type, volMesh>& su,
2648  const tmp<fvMatrix<Type>>& tA
2649 )
2650 {
2651  checkMethod(tA(), su, "-");
2652  tmp<fvMatrix<Type>> tC(tA.ptr());
2653  tC.ref().negate();
2654  tC.ref().source() -= su.mesh().V()*su.field();
2655  return tC;
2656 }
2657 
2658 template<class Type>
2659 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2660 (
2661  const tmp<DimensionedField<Type, volMesh>>& tsu,
2662  const tmp<fvMatrix<Type>>& tA
2663 )
2664 {
2665  checkMethod(tA(), tsu(), "-");
2666  tmp<fvMatrix<Type>> tC(tA.ptr());
2667  tC.ref().negate();
2668  tC.ref().source() -= tsu().mesh().V()*tsu().field();
2669  tsu.clear();
2670  return tC;
2671 }
2672 
2673 template<class Type>
2674 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2675 (
2676  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tsu,
2677  const tmp<fvMatrix<Type>>& tA
2678 )
2679 {
2680  checkMethod(tA(), tsu(), "-");
2681  tmp<fvMatrix<Type>> tC(tA.ptr());
2682  tC.ref().negate();
2683  tC.ref().source() -= tsu().mesh().V()*tsu().primitiveField();
2684  tsu.clear();
2685  return tC;
2686 }
2687 
2688 template<class Type>
2689 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2690 (
2691  const fvMatrix<Type>& A,
2692  const dimensioned<Type>& su
2693 )
2694 {
2695  checkMethod(A, su, "+");
2696  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2697  tC.ref().source() -= su.value()*A.psi().mesh().V();
2698  return tC;
2699 }
2700 
2701 template<class Type>
2702 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2703 (
2704  const tmp<fvMatrix<Type>>& tA,
2705  const dimensioned<Type>& su
2706 )
2707 {
2708  checkMethod(tA(), su, "+");
2709  tmp<fvMatrix<Type>> tC(tA.ptr());
2710  tC.ref().source() -= su.value()*tC().psi().mesh().V();
2711  return tC;
2712 }
2713 
2714 template<class Type>
2715 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2716 (
2717  const dimensioned<Type>& su,
2718  const fvMatrix<Type>& A
2719 )
2720 {
2721  checkMethod(A, su, "+");
2722  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2723  tC.ref().source() -= su.value()*A.psi().mesh().V();
2724  return tC;
2725 }
2726 
2727 template<class Type>
2728 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator+
2729 (
2730  const dimensioned<Type>& su,
2731  const tmp<fvMatrix<Type>>& tA
2732 )
2733 {
2734  checkMethod(tA(), su, "+");
2735  tmp<fvMatrix<Type>> tC(tA.ptr());
2736  tC.ref().source() -= su.value()*tC().psi().mesh().V();
2737  return tC;
2738 }
2739 
2740 template<class Type>
2741 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2742 (
2743  const fvMatrix<Type>& A,
2744  const dimensioned<Type>& su
2745 )
2746 {
2747  checkMethod(A, su, "-");
2748  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2749  tC.ref().source() += su.value()*tC().psi().mesh().V();
2750  return tC;
2751 }
2752 
2753 template<class Type>
2754 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2755 (
2756  const tmp<fvMatrix<Type>>& tA,
2757  const dimensioned<Type>& su
2758 )
2759 {
2760  checkMethod(tA(), su, "-");
2761  tmp<fvMatrix<Type>> tC(tA.ptr());
2762  tC.ref().source() += su.value()*tC().psi().mesh().V();
2763  return tC;
2764 }
2765 
2766 template<class Type>
2767 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2768 (
2769  const dimensioned<Type>& su,
2770  const fvMatrix<Type>& A
2771 )
2772 {
2773  checkMethod(A, su, "-");
2774  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2775  tC.ref().negate();
2776  tC.ref().source() -= su.value()*A.psi().mesh().V();
2777  return tC;
2778 }
2779 
2780 template<class Type>
2781 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator-
2782 (
2783  const dimensioned<Type>& su,
2784  const tmp<fvMatrix<Type>>& tA
2785 )
2786 {
2787  checkMethod(tA(), su, "-");
2788  tmp<fvMatrix<Type>> tC(tA.ptr());
2789  tC.ref().negate();
2790  tC.ref().source() -= su.value()*tC().psi().mesh().V();
2791  return tC;
2792 }
2793 
2794 
2795 template<class Type>
2796 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2797 (
2798  const volScalarField::Internal& dsf,
2799  const fvMatrix<Type>& A
2800 )
2801 {
2802  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2803  tC.ref() *= dsf;
2804  return tC;
2805 }
2806 
2807 template<class Type>
2808 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2809 (
2810  const tmp<volScalarField::Internal>& tdsf,
2811  const fvMatrix<Type>& A
2812 )
2813 {
2814  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2815  tC.ref() *= tdsf;
2816  return tC;
2817 }
2818 
2819 template<class Type>
2820 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2821 (
2822  const tmp<volScalarField>& tvsf,
2823  const fvMatrix<Type>& A
2824 )
2825 {
2826  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2827  tC.ref() *= tvsf;
2828  return tC;
2829 }
2830 
2831 template<class Type>
2832 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2833 (
2834  const volScalarField::Internal& dsf,
2835  const tmp<fvMatrix<Type>>& tA
2836 )
2837 {
2838  tmp<fvMatrix<Type>> tC(tA.ptr());
2839  tC.ref() *= dsf;
2840  return tC;
2841 }
2842 
2843 template<class Type>
2844 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2845 (
2846  const tmp<volScalarField::Internal>& tdsf,
2847  const tmp<fvMatrix<Type>>& tA
2848 )
2849 {
2850  tmp<fvMatrix<Type>> tC(tA.ptr());
2851  tC.ref() *= tdsf;
2852  return tC;
2853 }
2854 
2855 template<class Type>
2856 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2857 (
2858  const tmp<volScalarField>& tvsf,
2859  const tmp<fvMatrix<Type>>& tA
2860 )
2861 {
2862  tmp<fvMatrix<Type>> tC(tA.ptr());
2863  tC.ref() *= tvsf;
2864  return tC;
2865 }
2866 
2867 template<class Type>
2868 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2869 (
2870  const dimensioned<scalar>& ds,
2871  const fvMatrix<Type>& A
2872 )
2873 {
2874  tmp<fvMatrix<Type>> tC(new fvMatrix<Type>(A));
2875  tC.ref() *= ds;
2876  return tC;
2877 }
2878 
2879 template<class Type>
2880 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator*
2881 (
2882  const dimensioned<scalar>& ds,
2883  const tmp<fvMatrix<Type>>& tA
2884 )
2885 {
2886  tmp<fvMatrix<Type>> tC(tA.ptr());
2887  tC.ref() *= ds;
2888  return tC;
2889 }
2890 
2891 
2892 template<class Type>
2894 Foam::operator&
2895 (
2896  const fvMatrix<Type>& M,
2897  const DimensionedField<Type, volMesh>& psi
2898 )
2899 {
2900  tmp<GeometricField<Type, fvPatchField, volMesh>> tMphi
2901  (
2902  new GeometricField<Type, fvPatchField, volMesh>
2903  (
2904  IOobject
2905  (
2906  "M&" + psi.name(),
2907  psi.instance(),
2908  psi.mesh(),
2911  ),
2912  psi.mesh(),
2913  M.dimensions()/dimVol,
2914  extrapolatedCalculatedFvPatchScalarField::typeName
2915  )
2916  );
2917  GeometricField<Type, fvPatchField, volMesh>& Mphi = tMphi.ref();
2918 
2919  // Loop over field components
2920  if (M.hasDiag())
2921  {
2922  for (direction cmpt=0; cmpt<pTraits<Type>::nComponents; cmpt++)
2923  {
2924  scalarField psiCmpt(psi.field().component(cmpt));
2925  scalarField boundaryDiagCmpt(M.diag());
2926  M.addBoundaryDiag(boundaryDiagCmpt, cmpt);
2927  Mphi.primitiveFieldRef().replace(cmpt, -boundaryDiagCmpt*psiCmpt);
2928  }
2929  }
2930  else
2931  {
2932  Mphi.primitiveFieldRef() = Zero;
2933  }
2934 
2935  Mphi.primitiveFieldRef() += M.lduMatrix::H(psi.field()) + M.source();
2936  M.addBoundarySource(Mphi.primitiveFieldRef());
2937 
2938  Mphi.primitiveFieldRef() /= -psi.mesh().V();
2939  Mphi.correctBoundaryConditions();
2940 
2941  return tMphi;
2942 }
2943 
2944 template<class Type>
2946 Foam::operator&
2947 (
2948  const fvMatrix<Type>& M,
2949  const tmp<DimensionedField<Type, volMesh>>& tpsi
2950 )
2951 {
2952  tmp<GeometricField<Type, fvPatchField, volMesh>> tMpsi = M & tpsi();
2953  tpsi.clear();
2954  return tMpsi;
2955 }
2956 
2957 template<class Type>
2959 Foam::operator&
2960 (
2961  const fvMatrix<Type>& M,
2962  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tpsi
2963 )
2964 {
2965  tmp<GeometricField<Type, fvPatchField, volMesh>> tMpsi = M & tpsi();
2966  tpsi.clear();
2967  return tMpsi;
2968 }
2969 
2970 template<class Type>
2972 Foam::operator&
2973 (
2974  const tmp<fvMatrix<Type>>& tM,
2975  const DimensionedField<Type, volMesh>& psi
2976 )
2977 {
2978  tmp<GeometricField<Type, fvPatchField, volMesh>> tMpsi = tM() & psi;
2979  tM.clear();
2980  return tMpsi;
2981 }
2982 
2983 template<class Type>
2985 Foam::operator&
2986 (
2987  const tmp<fvMatrix<Type>>& tM,
2988  const tmp<DimensionedField<Type, volMesh>>& tpsi
2989 )
2990 {
2991  tmp<GeometricField<Type, fvPatchField, volMesh>> tMpsi = tM() & tpsi();
2992  tM.clear();
2993  tpsi.clear();
2994  return tMpsi;
2995 }
2996 
2997 template<class Type>
2999 Foam::operator&
3000 (
3001  const tmp<fvMatrix<Type>>& tM,
3002  const tmp<GeometricField<Type, fvPatchField, volMesh>>& tpsi
3003 )
3004 {
3005  tmp<GeometricField<Type, fvPatchField, volMesh>> tMpsi = tM() & tpsi();
3006  tM.clear();
3007  tpsi.clear();
3008  return tMpsi;
3009 }
3010 
3011 
3012 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
3013 
3014 template<class Type>
3015 Foam::Ostream& Foam::operator<<(Ostream& os, const fvMatrix<Type>& fvm)
3016 {
3017  os << static_cast<const lduMatrix&>(fvm) << nl
3018  << fvm.dimensions_ << nl
3019  << fvm.source_ << nl
3020  << fvm.internalCoeffs_ << nl
3021  << fvm.boundaryCoeffs_ << endl;
3022 
3024 
3025  return os;
3026 }
3027 
3028 
3029 // * * * * * * * * * * * * * * * * Solvers * * * * * * * * * * * * * * * * * //
3030 
3031 #include "fvMatrixSolve.C"
3032 
3033 // ************************************************************************* //
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...
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:51
tmp< Field< Type > > faceH(const Field< Type > &) const
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
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:46
label faceId(-1)
T & last()
Return reference to the last element of the list.
Definition: UPtrList.H:639
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.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
UEqn relax()
void relax()
Relax matrix (for steady-state solution).
Definition: fvMatrix.C:1248
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:1627
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
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:463
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:1010
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:1340
A traits class, which is primarily used for primitives.
Definition: pTraits.H:50
void operator-=(const fvMatrix< Type > &)
Definition: fvMatrix.C:1680
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:1187
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:806
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:1402
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.
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:80
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: UPtrListI.H:134
tmp< scalarField > D() const
Return the matrix scalar diagonal.
Definition: fvMatrix.C:1278
void operator=(const fvMatrix< Type > &)
Definition: fvMatrix.C:1582
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:84
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:486
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
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:1071
Generic templated field type.
Definition: Field.H:61
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:1026
#define DebugInFunction
Report an information message using Foam::Info.
void checkMethod(const faMatrix< Type > &, const faMatrix< Type > &, const char *)
Definition: faMatrix.C:1057
virtual const lduAddressing & lduAddr() const
Return ldu addressing.
virtual ~fvMatrix()
Destructor.
Definition: fvMatrix.C:464
virtual bool coupled() const
True if this patch field is coupled.
Definition: fvPatchField.H:565
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.
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:221
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:1642
tmp< Field< Type > > DD() const
Return the matrix Type diagonal.
Definition: fvMatrix.C:1287
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:1311
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:1171
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:57
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)
Internal & ref(const bool updateAccessTime=true)
Same as internalFieldRef()
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:58
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:263
const volScalarField & psi
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > flux() const
Return the face-flux field from the matrix.
Definition: fvMatrix.C:1451
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:977
void boundaryManipulate(typename GeometricField< Type, fvPatchField, volMesh >::Boundary &values)
Manipulate based on a boundary field.
Definition: fvMatrix.C:1265
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:231
List< label > labelList
A List of labels.
Definition: List.H:62
void clearOut()
Clear additional addressing.
A class for managing temporary objects.
Definition: HashPtrTable.H:50
void setSize(const label n)
Alias for resize()
Definition: UPtrList.H:337
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
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)
tmp< DimensionedField< typename DimensionedField< Type, GeoMesh >::cmptType, GeoMesh >> cmptAv(const DimensionedField< Type, GeoMesh > &df)
This boundary condition enforces a cyclic condition between a pair of boundaries, whereby communicati...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
List< cell > cellList
A List of cells.
Definition: cellListFwd.H:41
static const Foam::dimensionedScalar B("", Foam::dimless, 18.678)
const dimensionSet & dimensions() const noexcept
Return dimensions.
const dictionary & solverDict() const
Return the solver dictionary taking into account finalIteration.
Definition: fvMatrix.C:1566
#define InfoInFunction
Report an information message using Foam::Info.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157
void append(autoPtr< T > &ptr)
Move append an element to the end of the list.
Definition: PtrDynList.H:322
void replace(const direction d, const GeometricField< cmptType, PatchField, GeoMesh > &gcf)
Replace specified field component with content from another field.