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