MomentumTransferPhaseSystem.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) 2015-2018 OpenFOAM Foundation
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
29 
30 #include "BlendedInterfacialModel.H"
31 #include "dragModel.H"
32 #include "virtualMassModel.H"
33 #include "liftModel.H"
34 #include "wallLubricationModel.H"
35 #include "turbulentDispersionModel.H"
36 
37 #include "HashPtrTable.H"
38 
39 #include "fvmDdt.H"
40 #include "fvmDiv.H"
41 #include "fvmSup.H"
42 #include "fvcAverage.H"
43 #include "fvcDdt.H"
44 #include "fvcDiv.H"
45 #include "fvcFlux.H"
46 #include "fvcSnGrad.H"
47 #include "fvMatrix.H"
48 
49 
50 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
51 
52 template<class BasePhaseSystem>
55 (
56  const phasePairKey& key
57 ) const
58 {
59  if (dragModels_.found(key))
60  {
61  return dragModels_[key]->K();
62  }
63  else
64  {
65  return volScalarField::New
66  (
67  dragModel::typeName + ":K",
68  this->mesh_,
69  dimensionedScalar(dragModel::dimK)
70  );
71  }
72 }
73 
74 
75 template<class BasePhaseSystem>
78 (
79  const phasePairKey& key
80 ) const
81 {
82  if (dragModels_.found(key))
83  {
84  return dragModels_[key]->Kf();
85  }
86  else
87  {
89  (
90  dragModel::typeName + ":K",
91  this->mesh_,
92  dimensionedScalar(dragModel::dimK)
93  );
94  }
95 }
96 
97 
98 template<class BasePhaseSystem>
101 (
102  const phasePairKey& key
103 ) const
104 {
105  if (virtualMassModels_.found(key))
106  {
107  return virtualMassModels_[key]->K();
108  }
109  else
110  {
111  return volScalarField::New
112  (
113  virtualMassModel::typeName + ":K",
114  this->mesh_,
115  dimensionedScalar(virtualMassModel::dimK)
116  );
117  }
118 }
119 
120 
121 template<class BasePhaseSystem>
123 addMassTransferMomentumTransfer(phaseSystem::momentumTransferTable& eqns) const
124 {
126  (
127  phaseSystem::phasePairTable,
128  this->phasePairs_,
129  phasePairIter
130  )
131  {
132  const phasePair& pair(phasePairIter());
133 
134  if (pair.ordered())
135  {
136  continue;
137  }
138 
139  // Note that the phase UEqn contains a continuity error term, which
140  // implicitly adds a mass transfer term of fvm::Sp(dmdt, U). These
141  // additions do not include this term.
142 
143  const volScalarField dmdt(this->dmdt(pair));
144 
145  if (!pair.phase1().stationary())
146  {
147  fvVectorMatrix& eqn = *eqns[pair.phase1().name()];
148  const volScalarField dmdt21(posPart(dmdt));
149 
150  eqn += dmdt21*pair.phase2().U() - fvm::Sp(dmdt21, eqn.psi());
151  }
152 
153  if (!pair.phase2().stationary())
154  {
155  fvVectorMatrix& eqn = *eqns[pair.phase2().name()];
156  const volScalarField dmdt12(negPart(dmdt));
157 
158  eqn -= dmdt12*pair.phase1().U() - fvm::Sp(dmdt12, eqn.psi());
159  }
160  }
161 }
162 
163 
164 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
165 
166 template<class BasePhaseSystem>
169 (
170  const fvMesh& mesh
171 )
172 :
173  BasePhaseSystem(mesh)
174 {
175  this->generatePairsAndSubModels
176  (
177  "drag",
178  dragModels_
179  );
180 
181  this->generatePairsAndSubModels
182  (
183  "virtualMass",
184  virtualMassModels_
185  );
186 
187  this->generatePairsAndSubModels
188  (
189  "lift",
190  liftModels_
191  );
192 
193  this->generatePairsAndSubModels
194  (
195  "wallLubrication",
196  wallLubricationModels_
197  );
198 
199  this->generatePairsAndSubModels
200  (
201  "turbulentDispersion",
202  turbulentDispersionModels_
203  );
204 
206  (
208  dragModels_,
209  dragModelIter
210  )
211  {
212  const phasePair& pair(this->phasePairs_[dragModelIter.key()]);
213 
214  Kds_.set
215  (
216  pair,
217  new volScalarField
218  (
219  IOobject::groupName("Kd", pair.name()),
220  dragModelIter()->K()
221  )
222  );
223 
224  Kdfs_.set
225  (
226  pair,
228  (
229  IOobject::groupName("Kdf", pair.name()),
230  dragModelIter()->Kf()
231  )
232  );
233  }
234 
236  (
238  virtualMassModels_,
239  virtualMassModelIter
240  )
241  {
242  const phasePair& pair(this->phasePairs_[virtualMassModelIter.key()]);
243 
244  Vms_.set
245  (
246  pair,
247  new volScalarField
248  (
249  IOobject::groupName("Vm", pair.name()),
250  virtualMassModelIter()->K()
251  )
252  );
253 
254  Vmfs_.set
255  (
256  pair,
258  (
259  IOobject::groupName("Vmf", pair.name()),
260  virtualMassModelIter()->Kf()
261  )
262  );
263  }
264 }
265 
266 
267 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
268 
269 template<class BasePhaseSystem>
272 {}
273 
274 
275 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
276 
277 template<class BasePhaseSystem>
280 {
281  // Create a momentum transfer matrix for each phase
283  (
285  );
286 
287  phaseSystem::momentumTransferTable& eqns = eqnsPtr();
288 
289  forAll(this->movingPhases(), movingPhasei)
290  {
291  const phaseModel& phase = this->movingPhases()[movingPhasei];
292 
293  eqns.set
294  (
295  phase.name(),
297  );
298  }
299 
300  // Update the drag coefficients
302  (
304  dragModels_,
305  dragModelIter
306  )
307  {
308  *Kds_[dragModelIter.key()] = dragModelIter()->K();
309  *Kdfs_[dragModelIter.key()] = dragModelIter()->Kf();
310  }
311 
312  // Add the implicit part of the drag force
313  forAllConstIter(KdTable, Kds_, KdIter)
314  {
315  const volScalarField& K(*KdIter());
316  const phasePair& pair(this->phasePairs_[KdIter.key()]);
317 
318  forAllConstIter(phasePair, pair, iter)
319  {
320  if (!iter().stationary())
321  {
322  fvVectorMatrix& eqn = *eqns[iter().name()];
323 
324  eqn -= fvm::Sp(K, eqn.psi());
325  }
326  }
327  }
328 
329  // Update the virtual mass coefficients
331  (
333  virtualMassModels_,
334  virtualMassModelIter
335  )
336  {
337  *Vms_[virtualMassModelIter.key()] = virtualMassModelIter()->K();
338  *Vmfs_[virtualMassModelIter.key()] = virtualMassModelIter()->Kf();
339  }
340 
341  // Add the virtual mass force
342  forAllConstIter(VmTable, Vms_, VmIter)
343  {
344  const volScalarField& Vm(*VmIter());
345  const phasePair& pair(this->phasePairs_[VmIter.key()]);
346 
347  forAllConstIter(phasePair, pair, iter)
348  {
349  const phaseModel& phase = iter();
350  const phaseModel& otherPhase = iter.otherPhase();
351 
352  if (!phase.stationary())
353  {
354  fvVectorMatrix& eqn = *eqns[phase.name()];
355 
356  const volVectorField& U = eqn.psi();
357  const surfaceScalarField& phi = phase.phi();
358 
359  eqn -=
360  Vm
361  *(
362  fvm::ddt(U)
363  + fvm::div(phi, U)
364  - fvm::Sp(fvc::div(phi), U)
365  - otherPhase.DUDt()
366  )
367  + this->MRF_.DDt(Vm, U - otherPhase.U());
368  }
369  }
370  }
371 
372  // Add the source term due to mass transfer
373  addMassTransferMomentumTransfer(eqns);
374 
375  return eqnsPtr;
376 }
377 
378 
379 template<class BasePhaseSystem>
382 {
383  // Create a momentum transfer matrix for each phase
385  (
387  );
388 
389  phaseSystem::momentumTransferTable& eqns = eqnsPtr();
390 
391  forAll(this->movingPhases(), movingPhasei)
392  {
393  const phaseModel& phase = this->movingPhases()[movingPhasei];
394 
395  eqns.set
396  (
397  phase.name(),
399  );
400  }
401 
402  // Create U & grad(U) fields
403  PtrList<fvVectorMatrix> UgradUs(this->phaseModels_.size());
404  forAll(this->phaseModels_, phasei)
405  {
406  const phaseModel& phase = this->phaseModels_[phasei];
407 
408  if (!phase.stationary())
409  {
410  const volVectorField& U = phase.U();
411 
412  UgradUs.set
413  (
414  phasei,
415  new fvVectorMatrix
416  (
417  fvm::div(phase.phi(), U)
418  - fvm::Sp(fvc::div(phase.phi()), U)
419  + this->MRF().DDt(U)
420  )
421  );
422  }
423  }
424 
425  // Add the virtual mass force
426  forAllConstIter(VmTable, Vms_, VmIter)
427  {
428  const volScalarField& Vm(*VmIter());
429  const phasePair& pair(this->phasePairs_[VmIter.key()]);
430 
431  forAllConstIter(phasePair, pair, iter)
432  {
433  const phaseModel& phase = iter();
434  const phaseModel& otherPhase = iter.otherPhase();
435 
436  if (!phase.stationary())
437  {
438  *eqns[phase.name()] -=
439  Vm
440  *(
441  UgradUs[phase.index()]
442  - (UgradUs[otherPhase.index()] & otherPhase.U())
443  );
444  }
445  }
446  }
447 
448  // Add the source term due to mass transfer
449  addMassTransferMomentumTransfer(eqns);
450 
451  return eqnsPtr;
452 }
453 
454 
455 template<class BasePhaseSystem>
458 {
459  PtrList<surfaceScalarField> AFfs(this->phaseModels_.size());
460 
461  // Add the implicit part of the drag force
462  forAllConstIter(KdfTable, Kdfs_, KdfIter)
463  {
464  const surfaceScalarField& Kf(*KdfIter());
465  const phasePair& pair(this->phasePairs_[KdfIter.key()]);
466 
467  forAllConstIter(phasePair, pair, iter)
468  {
469  this->addField(iter(), "AFf", Kf, AFfs);
470  }
471  }
472 
473  // Add the implicit part of the virtual mass force
474  forAllConstIter(VmfTable, Vmfs_, VmfIter)
475  {
476  const surfaceScalarField& Vmf(*VmfIter());
477  const phasePair& pair(this->phasePairs_[VmfIter.key()]);
478 
479  forAllConstIter(phasePair, pair, iter)
480  {
481  this->addField(iter(), "AFf", byDt(Vmf), AFfs);
482  }
483  }
484 
485  if (this->fillFields_)
486  {
487  this->fillFields("AFf", dimDensity/dimTime, AFfs);
488  }
489 
490  return AFfs;
491 }
492 
493 
494 template<class BasePhaseSystem>
497 (
499 )
500 {
501  PtrList<surfaceScalarField> phiFs(this->phaseModels_.size());
502 
503  // Add the lift force
505  (
507  liftModels_,
508  liftModelIter
509  )
510  {
511  const volVectorField F(liftModelIter()->F<vector>());
512  const phasePair& pair(this->phasePairs_[liftModelIter.key()]);
513 
514  this->addField
515  (
516  pair.phase1(),
517  "phiF",
518  fvc::flux(rAUs[pair.phase1().index()]*F),
519  phiFs
520  );
521  this->addField
522  (
523  pair.phase2(),
524  "phiF",
525  - fvc::flux(rAUs[pair.phase2().index()]*F),
526  phiFs
527  );
528  }
529 
530  // Add the wall lubrication force
532  (
534  wallLubricationModels_,
535  wallLubricationModelIter
536  )
537  {
538  const volVectorField F(wallLubricationModelIter()->F<vector>());
539  const phasePair&
540  pair(this->phasePairs_[wallLubricationModelIter.key()]);
541 
542  this->addField
543  (
544  pair.phase1(),
545  "phiF",
546  fvc::flux(rAUs[pair.phase1().index()]*F),
547  phiFs
548  );
549  this->addField
550  (
551  pair.phase2(),
552  "phiF",
553  - fvc::flux(rAUs[pair.phase2().index()]*F),
554  phiFs
555  );
556  }
557 
558  // Add the phase pressure
559  DByAfs_.clear();
560  forAll(this->phaseModels_, phasei)
561  {
562  const phaseModel& phase = this->phaseModels_[phasei];
563 
564  const surfaceScalarField pPrimeByAf
565  (
566  fvc::interpolate(rAUs[phasei]*phase.pPrime())
567  );
568 
570  (
571  fvc::snGrad(phase)*this->mesh_.magSf()
572  );
573 
574  this->addField(phase, "phiF", pPrimeByAf*snGradAlpha1, phiFs);
575 
576  const bool implicitPhasePressure =
577  this->mesh_.solverDict(phase.volScalarField::name()).
578  template lookupOrDefault<Switch>
579  (
580  "implicitPhasePressure",
581  false
582  );
583 
584  if (implicitPhasePressure)
585  {
586  this->addField(phase, "DByAf", pPrimeByAf, DByAfs_);
587  }
588  }
589 
590  // Add the turbulent dispersion force
592  (
594  turbulentDispersionModels_,
595  turbulentDispersionModelIter
596  )
597  {
598  const phasePair&
599  pair(this->phasePairs_[turbulentDispersionModelIter.key()]);
600 
601  const volScalarField D(turbulentDispersionModelIter()->D());
602 
603  const surfaceScalarField DByA1f
604  (
605  fvc::interpolate(rAUs[pair.phase1().index()]*D)
606  );
607  const surfaceScalarField DByA2f
608  (
609  fvc::interpolate(rAUs[pair.phase2().index()]*D)
610  );
611 
613  (
614  fvc::snGrad(pair.phase1())*this->mesh_.magSf()
615  );
616 
617  this->addField(pair.phase1(), "phiF", DByA1f*snGradAlpha1, phiFs);
618  this->addField(pair.phase2(), "phiF", - DByA2f*snGradAlpha1, phiFs);
619 
620  if (DByAfs_.found(pair.phase1().name()))
621  {
622  this->addField(pair.phase1(), "DByAf", DByA1f, DByAfs_);
623  }
624  }
625 
626  if (this->fillFields_)
627  {
629  }
630 
631  return phiFs;
632 }
633 
634 
635 template<class BasePhaseSystem>
638 (
640 )
641 {
642  PtrList<surfaceScalarField> phiFfs(this->phaseModels_.size());
643 
644  // Add the explicit part of the virtual mass force
645  forAllConstIter(VmfTable, Vmfs_, VmfIter)
646  {
647  const surfaceScalarField& Vmf(*VmfIter());
648  const phasePair& pair(this->phasePairs_[VmfIter.key()]);
649 
650  forAllConstIter(phasePair, pair, iter)
651  {
652  this->addField
653  (
654  iter(),
655  "phiFf",
656  - rAUfs[iter().index()]*Vmf
657  *(
658  byDt(this->MRF().absolute(iter().phi()().oldTime()))
659  + iter.otherPhase().DUDtf()
660  ),
661  phiFfs
662  );
663  }
664  }
665 
666  // Add the lift force
668  (
670  liftModels_,
671  liftModelIter
672  )
673  {
674  const surfaceScalarField Ff(liftModelIter()->Ff());
675  const phasePair& pair(this->phasePairs_[liftModelIter.key()]);
676 
677  this->addField
678  (
679  pair.phase1(),
680  "phiFs",
681  rAUfs[pair.phase1().index()]*Ff,
682  phiFfs
683  );
684  this->addField
685  (
686  pair.phase2(),
687  "phiFf",
688  - rAUfs[pair.phase2().index()]*Ff,
689  phiFfs
690  );
691  }
692 
693  // Add the wall lubrication force
695  (
697  wallLubricationModels_,
698  wallLubricationModelIter
699  )
700  {
701  const surfaceScalarField Ff(wallLubricationModelIter()->Ff());
702  const phasePair&
703  pair(this->phasePairs_[wallLubricationModelIter.key()]);
704 
705  this->addField
706  (
707  pair.phase1(),
708  "phiFf",
709  rAUfs[pair.phase1().index()]*Ff,
710  phiFfs
711  );
712  this->addField
713  (
714  pair.phase2(),
715  "phiFf",
716  - rAUfs[pair.phase2().index()]*Ff,
717  phiFfs
718  );
719  }
720 
721  // Add the phase pressure
722  DByAfs_.clear();
723  forAll(this->phaseModels_, phasei)
724  {
725  const phaseModel& phase = this->phaseModels_[phasei];
726 
727  const surfaceScalarField pPrimeByAf
728  (
730  );
731 
733  (
734  fvc::snGrad(phase)*this->mesh_.magSf()
735  );
736 
737  this->addField(phase, "phiFf", pPrimeByAf*snGradAlpha1, phiFfs);
738 
739  const bool implicitPhasePressure =
740  this->mesh_.solverDict(phase.volScalarField::name()).
741  template lookupOrDefault<Switch>
742  (
743  "implicitPhasePressure",
744  false
745  );
746 
747  if (implicitPhasePressure)
748  {
749  this->addField(phase, "DByAf", pPrimeByAf, DByAfs_);
750  }
751  }
752 
753  // Add the turbulent dispersion force and phase pressure
755  (
757  turbulentDispersionModels_,
758  turbulentDispersionModelIter
759  )
760  {
761  const phasePair&
762  pair(this->phasePairs_[turbulentDispersionModelIter.key()]);
763 
764  const volScalarField D(turbulentDispersionModelIter()->D());
765 
766  const surfaceScalarField DByAf1
767  (
768  rAUfs[pair.phase1().index()]*fvc::interpolate(D)
769  );
770  const surfaceScalarField DByAf2
771  (
772  rAUfs[pair.phase2().index()]*fvc::interpolate(D)
773  );
774 
776  (
777  fvc::snGrad(pair.phase1())*this->mesh_.magSf()
778  );
779 
780  this->addField(pair.phase1(), "phiFf", DByAf1*snGradAlpha1, phiFfs);
781  this->addField(pair.phase2(), "phiFf", - DByAf2*snGradAlpha1, phiFfs);
782 
783  if (DByAfs_.found(pair.phase1().name()))
784  {
785  this->addField(pair.phase1(), "DByAf", DByAf1, DByAfs_);
786  }
787  }
788 
789  if (this->fillFields_)
790  {
792  }
793 
794  return phiFfs;
795 }
796 
797 
798 template<class BasePhaseSystem>
801 (
803 ) const
804 {
805  PtrList<surfaceScalarField> phiKdPhis(this->phaseModels_.size());
806 
807  // Add the explicit part of the drag force
808  forAllConstIter(KdTable, Kds_, KdIter)
809  {
810  const volScalarField& K(*KdIter());
811  const phasePair& pair(this->phasePairs_[KdIter.key()]);
812 
813  forAllConstIter(phasePair, pair, iter)
814  {
815  this->addField
816  (
817  iter(),
818  "phiKdPhi",
819  - fvc::interpolate(rAUs[iter().index()]*K)
820  *this->MRF().absolute(iter.otherPhase().phi()),
821  phiKdPhis
822  );
823  }
824  }
825 
826  if (this->fillFields_)
827  {
828  this->fillFields
829  (
830  "phiKdPhi",
832  phiKdPhis
833  );
834  }
835 
836  return phiKdPhis;
837 }
838 
839 
840 template<class BasePhaseSystem>
843 (
845 ) const
846 {
847  PtrList<surfaceScalarField> phiKdPhifs(this->phaseModels_.size());
848 
849  // Add the explicit part of the drag force
850  forAllConstIter(KdfTable, Kdfs_, KdfIter)
851  {
852  const surfaceScalarField& Kf(*KdfIter());
853  const phasePair& pair(this->phasePairs_[KdfIter.key()]);
854 
855  forAllConstIter(phasePair, pair, iter)
856  {
857  this->addField
858  (
859  iter(),
860  "phiKdPhif",
861  - rAUfs[iter().index()]*Kf
862  *this->MRF().absolute(iter.otherPhase().phi()),
863  phiKdPhifs
864  );
865  }
866  }
867 
868  if (this->fillFields_)
869  {
870  this->fillFields
871  (
872  "phiKdPhif",
874  phiKdPhifs
875  );
876  }
877 
878  return phiKdPhifs;
879 }
880 
881 
882 template<class BasePhaseSystem>
885 (
887 ) const
888 {
889  PtrList<volVectorField> KdUByAs(this->phaseModels_.size());
890 
891  // Add the explicit part of the drag force
892  forAllConstIter(KdTable, Kds_, KdIter)
893  {
894  const volScalarField& K(*KdIter());
895  const phasePair& pair(this->phasePairs_[KdIter.key()]);
896 
897  forAllConstIter(phasePair, pair, iter)
898  {
899  this->addField
900  (
901  iter(),
902  "KdUByA",
903  - rAUs[iter().index()]*K*iter.otherPhase().U(),
904  KdUByAs
905  );
906  }
907  }
908 
909  if (this->fillFields_)
910  {
911  this->fillFields("KdUByA", dimVelocity, KdUByAs);
912  }
913 
914  return KdUByAs;
915 }
916 
917 
918 template<class BasePhaseSystem>
921 (
923  const bool includeVirtualMass
924 ) const
925 {
926  PtrList<surfaceScalarField> ddtCorrByAs(this->phaseModels_.size());
927 
928  // Construct phi differences
929  PtrList<surfaceScalarField> phiCorrs(this->phaseModels_.size());
930  forAll(this->phaseModels_, phasei)
931  {
932  const phaseModel& phase = this->phaseModels_[phasei];
933 
934  phiCorrs.set
935  (
936  phasei,
937  this->MRF().absolute(phase.phi()().oldTime())
938  - fvc::flux(phase.U()().oldTime())
939  );
940  }
941 
942  // Add correction
943  forAll(this->phaseModels_, phasei)
944  {
945  const phaseModel& phase = this->phaseModels_[phasei];
946  const volScalarField& alpha = phase;
947 
948  // Apply ddtPhiCorr filter in pure(ish) phases
949  surfaceScalarField alphafBar
950  (
952  );
953 
954  tmp<surfaceScalarField> phiCorrCoeff = pos0(alphafBar - 0.99);
955 
956  surfaceScalarField::Boundary& phiCorrCoeffBf =
957  phiCorrCoeff.ref().boundaryFieldRef();
958 
959  forAll(this->mesh_.boundary(), patchi)
960  {
961  // Set ddtPhiCorr to 0 on non-coupled boundaries
962  if
963  (
964  !this->mesh_.boundary()[patchi].coupled()
965  || isA<cyclicAMIFvPatch>(this->mesh_.boundary()[patchi])
966  )
967  {
968  phiCorrCoeffBf[patchi] = 0;
969  }
970  }
971 
972  this->addField
973  (
974  phase,
975  "ddtCorrByA",
976  - phiCorrCoeff*phiCorrs[phasei]*fvc::interpolate
977  (
978  byDt(alpha.oldTime()*phase.rho()().oldTime()*rAUs[phasei])
979  ),
980  ddtCorrByAs
981  );
982  }
983 
984  // Add virtual mass correction
985  if (includeVirtualMass)
986  {
987  forAllConstIter(VmTable, Vms_, VmIter)
988  {
989  const volScalarField& Vm(*VmIter());
990  const phasePair& pair(this->phasePairs_[VmIter.key()]);
991 
992  forAllConstIter(phasePair, pair, iter)
993  {
994  const phaseModel& phase = iter();
995  const phaseModel& otherPhase = iter.otherPhase();
996 
997  this->addField
998  (
999  iter(),
1000  "ddtCorrByA",
1001  - fvc::interpolate(Vm*byDt(rAUs[phase.index()]))
1002  *(
1003  phiCorrs[phase.index()]
1004  + this->MRF().absolute(otherPhase.phi())
1005  - fvc::flux(otherPhase.U())
1006  - phiCorrs[otherPhase.index()]
1007  ),
1008  ddtCorrByAs
1009  );
1010  }
1011  }
1012  }
1013 
1014  return ddtCorrByAs;
1015 }
1016 
1017 
1018 template<class BasePhaseSystem>
1022 )
1023 {
1024  Info<< "Inverting drag systems: ";
1025 
1026  phaseSystem::phaseModelList& phases = this->phaseModels_;
1027 
1028  // Create drag coefficient matrices
1029  PtrList<PtrList<volScalarField>> KdByAs(phases.size());
1031 
1032  forAll(phases, phasei)
1033  {
1034  KdByAs.set
1035  (
1036  phasei,
1037  new PtrList<volScalarField>(phases.size())
1038  );
1039 
1040  phiKds.set
1041  (
1042  phasei,
1044  );
1045  }
1046 
1047  forAllConstIter(KdTable, Kds_, KdIter)
1048  {
1049  const volScalarField& K(*KdIter());
1050  const phasePair& pair(this->phasePairs_[KdIter.key()]);
1051 
1052  const label phase1i = pair.phase1().index();
1053  const label phase2i = pair.phase2().index();
1054 
1055  this->addField
1056  (
1057  pair.phase2(),
1058  "KdByA",
1059  - rAUs[phase1i]*K,
1060  KdByAs[phase1i]
1061  );
1062  this->addField
1063  (
1064  pair.phase1(),
1065  "KdByA",
1066  - rAUs[phase2i]*K,
1067  KdByAs[phase2i]
1068  );
1069 
1070  this->addField
1071  (
1072  pair.phase2(),
1073  "phiKd",
1074  fvc::interpolate(KdByAs[phase1i][phase2i]),
1075  phiKds[phase1i]
1076  );
1077  this->addField
1078  (
1079  pair.phase1(),
1080  "phiKd",
1081  fvc::interpolate(KdByAs[phase2i][phase1i]),
1082  phiKds[phase2i]
1083  );
1084  }
1085 
1086  forAll(phases, phasei)
1087  {
1088  this->fillFields("KdByAs", dimless, KdByAs[phasei]);
1089  this->fillFields("phiKds", dimless, phiKds[phasei]);
1090 
1091  KdByAs[phasei][phasei] = 1;
1092  phiKds[phasei][phasei] = 1;
1093  }
1094 
1095  // Decompose
1096  for (label i = 0; i < phases.size(); ++ i)
1097  {
1098  for (label j = i + 1; j < phases.size(); ++ j)
1099  {
1100  KdByAs[i][j] /= KdByAs[i][i];
1101  phiKds[i][j] /= phiKds[i][i];
1102  for (label k = i + 1; k < phases.size(); ++ k)
1103  {
1104  KdByAs[j][k] -= KdByAs[j][i]*KdByAs[i][k];
1105  phiKds[j][k] -= phiKds[j][i]*phiKds[i][k];
1106  }
1107  }
1108  }
1109  {
1110  volScalarField detKdByAs(KdByAs[0][0]);
1111  surfaceScalarField detPhiKdfs(phiKds[0][0]);
1112  for (label i = 1; i < phases.size(); ++ i)
1113  {
1114  detKdByAs *= KdByAs[i][i];
1115  detPhiKdfs *= phiKds[i][i];
1116  }
1117  Info<< "Min cell/face det = " << gMin(detKdByAs.primitiveField())
1118  << "/" << gMin(detPhiKdfs.primitiveField()) << endl;
1119  }
1120 
1121  // Solve for the velocities and fluxes
1122  for (label i = 1; i < phases.size(); ++ i)
1123  {
1124  if (!phases[i].stationary())
1125  {
1126  for (label j = 0; j < i; j ++)
1127  {
1128  phases[i].URef() -= KdByAs[i][j]*phases[j].U();
1129  phases[i].phiRef() -= phiKds[i][j]*phases[j].phi();
1130  }
1131  }
1132  }
1133  for (label i = phases.size() - 1; i >= 0; i --)
1134  {
1135  if (!phases[i].stationary())
1136  {
1137  for (label j = phases.size() - 1; j > i; j --)
1138  {
1139  phases[i].URef() -= KdByAs[i][j]*phases[j].U();
1140  phases[i].phiRef() -= phiKds[i][j]*phases[j].phi();
1141  }
1142  phases[i].URef() /= KdByAs[i][i];
1143  phases[i].phiRef() /= phiKds[i][i];
1144  }
1145  }
1146 }
1147 
1148 
1149 template<class BasePhaseSystem>
1153 )
1154 {
1155  Info<< "Inverting drag system: ";
1156 
1157  phaseSystem::phaseModelList& phases = this->phaseModels_;
1158 
1159  // Create drag coefficient matrix
1161 
1162  forAll(phases, phasei)
1163  {
1164  phiKdfs.set
1165  (
1166  phasei,
1168  );
1169  }
1170 
1171  forAllConstIter(KdfTable, Kdfs_, KdfIter)
1172  {
1173  const surfaceScalarField& K(*KdfIter());
1174  const phasePair& pair(this->phasePairs_[KdfIter.key()]);
1175 
1176  const label phase1i = pair.phase1().index();
1177  const label phase2i = pair.phase2().index();
1178 
1179  this->addField
1180  (
1181  pair.phase2(),
1182  "phiKdf",
1183  - rAUfs[phase1i]*K,
1184  phiKdfs[phase1i]
1185  );
1186  this->addField
1187  (
1188  pair.phase1(),
1189  "phiKdf",
1190  - rAUfs[phase2i]*K,
1191  phiKdfs[phase2i]
1192  );
1193  }
1194 
1195  forAll(phases, phasei)
1196  {
1197  this->fillFields("phiKdf", dimless, phiKdfs[phasei]);
1198 
1199  phiKdfs[phasei][phasei] = 1;
1200  }
1201 
1202  // Decompose
1203  for (label i = 0; i < phases.size(); ++ i)
1204  {
1205  for (label j = i + 1; j < phases.size(); ++ j)
1206  {
1207  phiKdfs[i][j] /= phiKdfs[i][i];
1208  for (label k = i + 1; k < phases.size(); ++ k)
1209  {
1210  phiKdfs[j][k] -= phiKdfs[j][i]*phiKdfs[i][k];
1211  }
1212  }
1213  }
1214  {
1215  surfaceScalarField detPhiKdfs(phiKdfs[0][0]);
1216  for (label i = 1; i < phases.size(); ++ i)
1217  {
1218  detPhiKdfs *= phiKdfs[i][i];
1219  }
1220  Info<< "Min face det = " << gMin(detPhiKdfs.primitiveField()) << endl;
1221  }
1222 
1223  // Solve for the fluxes
1224  for (label i = 1; i < phases.size(); ++ i)
1225  {
1226  if (!phases[i].stationary())
1227  {
1228  for (label j = 0; j < i; j ++)
1229  {
1230  phases[i].phiRef() -= phiKdfs[i][j]*phases[j].phi();
1231  }
1232  }
1233  }
1234  for (label i = phases.size() - 1; i >= 0; i --)
1235  {
1236  if (!phases[i].stationary())
1237  {
1238  for (label j = phases.size() - 1; j > i; j --)
1239  {
1240  phases[i].phiRef() -= phiKdfs[i][j]*phases[j].phi();
1241  }
1242  phases[i].phiRef() /= phiKdfs[i][i];
1243  }
1244  }
1245 }
1246 
1247 
1248 template<class BasePhaseSystem>
1251 {
1252  return DByAfs_;
1253 }
1254 
1255 
1256 template<class BasePhaseSystem>
1258 {
1259  if (BasePhaseSystem::read())
1260  {
1261  bool readOK = true;
1262 
1263  // Read models ...
1264 
1265  return readOK;
1266  }
1267  else
1268  {
1269  return false;
1270  }
1271 }
1272 
1273 
1274 // ************************************************************************* //
Foam::MomentumTransferPhaseSystem::phiFfs
virtual PtrList< surfaceScalarField > phiFfs(const PtrList< surfaceScalarField > &rAUfs)
As phiFs, but for the face-based algorithm.
Definition: MomentumTransferPhaseSystem.C:638
Foam::phaseModel
Single incompressible phase derived from the phase-fraction. Used as part of the multiPhaseMixture fo...
Definition: phaseModel.H:57
Foam::fvc::snGrad
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > snGrad(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvcSnGrad.C:47
Foam::phasePair
Description for mass transfer between a pair of phases. The direction of the mass transfer is from th...
Definition: phasePair.H:51
Foam::phaseModel::index
label index() const
Return the index of the phase.
Definition: phaseModel.C:106
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Dimensionless.
Definition: dimensionSets.H:50
Foam::MomentumTransferPhaseSystem::~MomentumTransferPhaseSystem
virtual ~MomentumTransferPhaseSystem()
Destructor.
Definition: MomentumTransferPhaseSystem.C:271
rAUs
PtrList< volScalarField > rAUs
Definition: pEqn.H:4
MomentumTransferPhaseSystem.H
Foam::phase
Single incompressible phase derived from the phase-fraction. Used as part of the multiPhaseMixture fo...
Definition: phase.H:54
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::dimVelocity
const dimensionSet dimVelocity
Foam::dimDensity
const dimensionSet dimDensity
Foam::constant::atomic::alpha
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
Definition: readThermalProperties.H:212
Foam::posPart
dimensionedScalar posPart(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:221
Foam::GeometricField::primitiveField
const Internal::FieldType & primitiveField() const
Return a const-reference to the internal field.
Definition: GeometricFieldI.H:53
fvcSnGrad.H
Calculate the snGrad of the given volField.
Foam::MomentumTransferPhaseSystem::KdUByAs
virtual PtrList< volVectorField > KdUByAs(const PtrList< volScalarField > &rAUs) const
Return the explicit part of the drag force for the cell-based.
Definition: MomentumTransferPhaseSystem.C:885
Sp
zeroField Sp
Definition: alphaSuSp.H:2
oldTime
Info<< "Creating field kinetic energy K\n"<< endl;volScalarField K("K", 0.5 *magSqr(U));if(U.nOldTimes()){ volVectorField *Uold=&U.oldTime();volScalarField *Kold=&K.oldTime();*Kold==0.5 *magSqr(*Uold);while(Uold->nOldTimes()) { Uold=&Uold-> oldTime()
Definition: createK.H:12
fvcDiv.H
Calculate the divergence of the given field.
Foam::phaseModel::otherPhase
const phaseModel & otherPhase() const
Return the other phase in this two-phase system.
Ff
surfaceScalarField Ff(fluid.Ff())
F
volVectorField F(fluid.F())
phasei
label phasei
Definition: pEqn.H:27
fvMatrix.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::pos0
dimensionedScalar pos0(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:188
Foam::dimForce
const dimensionSet dimForce
Foam::fac::div
tmp< GeometricField< Type, faPatchField, areaMesh > > div(const GeometricField< Type, faePatchField, edgeMesh > &ssf)
Definition: facDiv.C:50
Foam::fvMatrix::psi
const GeometricField< Type, fvPatchField, volMesh > & psi() const
Definition: fvMatrix.H:285
forAllConstIter
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:338
fvmDiv.H
Calculate the matrix for the divergence of the given field and flux.
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
K
CGAL::Exact_predicates_exact_constructions_kernel K
Definition: CGALTriangulation3DKernel.H:58
Vmf
surfaceScalarField Vmf("Vmf", fluid.Vmf())
Foam::PtrListDictionary< phaseModel >
MRF
IOMRFZoneList & MRF
Definition: setRegionFluidFields.H:22
Foam::dimTime
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:54
Foam::tmp::ref
T & ref() const
Definition: tmpI.H:258
Foam::fvVectorMatrix
fvMatrix< vector > fvVectorMatrix
Definition: fvMatricesFwd.H:47
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::HashPtrTable::set
bool set(const Key &key, T *ptr)
Assign a new entry, overwriting existing entries.
Definition: HashPtrTableI.H:84
Foam::fac::average
tmp< GeometricField< Type, faPatchField, areaMesh > > average(const GeometricField< Type, faePatchField, edgeMesh > &ssf)
Area-weighted average a edgeField creating a areaField.
Definition: facAverage.C:47
AFfs
PtrList< surfaceScalarField > AFfs(fluid.AFfs())
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:43
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:65
phi
surfaceScalarField & phi
Definition: setRegionFluidFields.H:8
Foam::volScalarField
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:57
Foam::blockMeshTools::read
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:33
Foam::MomentumTransferPhaseSystem::partialElimination
virtual void partialElimination(const PtrList< volScalarField > &rAUs)
Solve the drag system for the velocities and fluxes.
Definition: MomentumTransferPhaseSystem.C:1020
Foam::MomentumTransferPhaseSystem::phiKdPhis
virtual PtrList< surfaceScalarField > phiKdPhis(const PtrList< volScalarField > &rAUs) const
Return the explicit drag force fluxes for the cell-based algorithm.
Definition: MomentumTransferPhaseSystem.C:801
Foam::MomentumTransferPhaseSystem::momentumTransferf
virtual autoPtr< phaseSystem::momentumTransferTable > momentumTransferf()
As momentumTransfer, but for the face-based algorithm.
Definition: MomentumTransferPhaseSystem.C:381
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::MomentumTransferPhaseSystem::MomentumTransferPhaseSystem
MomentumTransferPhaseSystem(const fvMesh &)
Construct from fvMesh.
Definition: MomentumTransferPhaseSystem.C:169
phiFfs
PtrList< surfaceScalarField > phiFfs(fluid.phiFfs(rAUfs))
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:84
Foam::MomentumTransferPhaseSystem::phiKdPhifs
virtual PtrList< surfaceScalarField > phiKdPhifs(const PtrList< surfaceScalarField > &rAUfs) const
As phiKdPhis, but for the face-based algorithm.
Definition: MomentumTransferPhaseSystem.C:843
Foam::dimMass
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:52
phiFs
PtrList< surfaceScalarField > phiFs(fluid.phiFs(rAUs))
snGradAlpha1
surfaceScalarField snGradAlpha1(fvc::snGrad(alpha1) *mesh.magSf())
fvmSup.H
Calculate the matrix for implicit and explicit sources.
Foam::phase::name
const word & name() const
Definition: phase.H:111
Foam::phaseModel::phi
virtual tmp< surfaceScalarField > phi() const =0
Return the volumetric flux.
Foam::HashTable< autoPtr< BlendedInterfacialModel< dragModel > >, phasePairKey, phasePairKey::hash >
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
fillFields
fluid fillFields("rAU", dimTime/dimDensity, rAUs)
Foam::MomentumTransferPhaseSystem::read
virtual bool read()
Read base phaseProperties dictionary.
Definition: MomentumTransferPhaseSystem.C:1257
Foam::MomentumTransferPhaseSystem::phiFs
virtual PtrList< surfaceScalarField > phiFs(const PtrList< volScalarField > &rAUs)
Return the explicit force fluxes for the cell-based algorithm, that.
Definition: MomentumTransferPhaseSystem.C:497
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
U
U
Definition: pEqn.H:72
Foam::negPart
dimensionedScalar negPart(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:232
rAUfs
PtrList< surfaceScalarField > rAUfs
Definition: pEqn.H:30
Foam::HashPtrTable
A HashTable of pointers to objects of type <T>.
Definition: HashPtrTable.H:54
Foam::fac::ddt
tmp< GeometricField< Type, faPatchField, areaMesh > > ddt(const dimensioned< Type > dt, const faMesh &mesh)
Definition: facDdt.C:47
fvcFlux.H
Calculate the face-flux of the given field.
phases
multiphaseSystem::phaseModelList & phases
Definition: createFields.H:12
HashPtrTable.H
k
label k
Boltzmann constant.
Definition: LISASMDCalcMethod2.H:41
D
const dimensionedScalar & D
Definition: solveBulkSurfactant.H:4
Foam::fvMatrix
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvPatchField.H:76
Foam::phaseModel::U
virtual tmp< volVectorField > U() const =0
Return the velocity.
Foam::MomentumTransferPhaseSystem::partialEliminationf
virtual void partialEliminationf(const PtrList< surfaceScalarField > &rAUfs)
As partialElimination, but for the face-based algorithm. Only solves.
Definition: MomentumTransferPhaseSystem.C:1151
fvcDdt.H
Calculate the first temporal derivative.
Foam::MomentumTransferPhaseSystem::momentumTransfer
virtual autoPtr< phaseSystem::momentumTransferTable > momentumTransfer()
Return the momentum transfer matrices for the cell-based algorithm.
Definition: MomentumTransferPhaseSystem.C:279
Foam::MomentumTransferPhaseSystem::AFfs
virtual PtrList< surfaceScalarField > AFfs() const
Return implicit force coefficients on the faces, for the face-based.
Definition: MomentumTransferPhaseSystem.C:457
Foam::gMin
Type gMin(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:593
Foam::fvc::flux
tmp< surfaceScalarField > flux(const volVectorField &vvf)
Return the face-flux field obtained from the given volVectorField.
Definition: fvcFlux.C:34
Foam::byDt
tmp< volScalarField > byDt(const volScalarField &vf)
Definition: phaseSystem.C:438
Foam::phasePair::phase1
const phaseModel & phase1() const
Return phase 1.
Definition: phasePairI.H:30
fvcAverage.H
Area-weighted average a surfaceField creating a volField.
Foam::GeometricField< scalar, fvPatchField, volMesh >
Foam::MomentumTransferPhaseSystem
Class which models interfacial momenum transfer between a number of phases. Drag, virtual mass,...
Definition: MomentumTransferPhaseSystem.H:66
Foam::fac::interpolate
static tmp< GeometricField< Type, faePatchField, edgeMesh > > interpolate(const GeometricField< Type, faPatchField, areaMesh > &tvf, const edgeScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
Foam::fvc::absolute
tmp< surfaceScalarField > absolute(const tmp< surfaceScalarField > &tphi, const volVectorField &U)
Return the given relative flux in absolute form.
Definition: fvcMeshPhi.C:190
Foam::MomentumTransferPhaseSystem::ddtCorrByAs
virtual PtrList< surfaceScalarField > ddtCorrByAs(const PtrList< volScalarField > &rAUs, const bool includeVirtualMass=false) const
Return the flux corrections for the cell-based algorithm. These.
Definition: MomentumTransferPhaseSystem.C:921
fvmDdt.H
Calulate the matrix for the first temporal derivative.
Foam::MomentumTransferPhaseSystem::DByAfs
virtual const HashPtrTable< surfaceScalarField > & DByAfs() const
Return the phase diffusivities divided by the momentum coefficients.
Definition: MomentumTransferPhaseSystem.C:1250
Foam::phaseModel::DUDt
virtual tmp< volVectorField > DUDt() const =0
Return the substantive acceleration.
Foam::phase::rho
const dimensionedScalar & rho() const
Return const-access to phase1 density.
Definition: phase.H:140