LagrangianEqn.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2025-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "LagrangianEqn.H"
27 #include "GeometricField.H"
28 #include "toSubField.H"
29 
30 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 
32 template<class Type>
33 template<class TypeB>
35 (
36  const tmp<LagrangianEqn<Type>>& tA,
37  const tmp<LagrangianEqn<TypeB>>& tB
38 ) const
39 {
40  // Check that the meshes are the same
41  if (&tA().mesh() != &tB().mesh())
42  {
44  << "Operating equations with different meshes"
45  << exit(FatalError);
46  }
47 
48  // Check that the referred fields are the same
49  const regIOobject& aPsi =
50  notNull(tA().psiSubSubRef_)
51  ? static_cast<const regIOobject&>(tA().psiSubSubRef_)
52  : notNull(tA().psiSubSub_)
53  ? static_cast<const regIOobject&>(tA().psiSubSub_)
54  : notNull(tA().psiSub_)
55  ? static_cast<const regIOobject&>(tA().psiSub_)
56  : NullObjectRef<regIOobject>();
57  const regIOobject& bPsi =
58  notNull(tB().psiSubSubRef_)
59  ? static_cast<const regIOobject&>(tB().psiSubSubRef_)
60  : notNull(tB().psiSubSub_)
61  ? static_cast<const regIOobject&>(tB().psiSubSub_)
62  : notNull(tB().psiSub_)
63  ? static_cast<const regIOobject&>(tB().psiSub_)
64  : NullObjectRef<regIOobject>();
65  if (notNull(aPsi) && notNull(bPsi) && &aPsi != &bPsi)
66  {
68  << "Operating equations with different fields"
69  << exit(FatalError);
70  }
71 }
72 
73 
74 template<class Type>
75 template<class OtherType>
77 (
78  const tmp<LagrangianEqn<OtherType>>& tOther
79 )
80 {
81  if (tOther().tDeltaT_.valid())
82  {
83  if (!tDeltaT_.valid())
84  {
85  tDeltaT_ =
86  tmp<LagrangianSubScalarField>
87  (
88  tOther().tDeltaT_,
89  tOther.isTmp()
90  );
91  }
92  else if (&tDeltaT_() != &tOther().tDeltaT_())
93  {
95  << "Operating equations with different time-step fields"
96  << exit(FatalError);
97  }
98  }
99 }
100 
101 
102 template<class Type>
103 template<class OtherType>
105 (
106  LagrangianEqn<OtherType>& other
107 )
108 {
109  // Remove old-time pointers so that they are not operated on on destruction
110  other.deltaTSp0Ptr_ = NullObjectPtr<LagrangianDynamicField<scalar>>();
111  other.S0Ptr_ = NullObjectPtr<LagrangianDynamicField<OtherType>>();
112 }
113 
114 
115 template<class Type>
116 template<class OtherType>
118 (
119  const tmp<LagrangianEqn<OtherType>>& tOther
120 )
121 {
122  if (tOther.isTmp())
123  {
124  opClear(tOther.ref());
125  }
126 }
127 
128 
129 template<class Type>
130 template<class OtherType>
132 (
133  LagrangianEqn<OtherType>& other
134 )
135 {
136  // Store previous implicit time coefficient and source fields
137  if (notNull(other.deltaTSp0Ptr_))
138  {
139  LagrangianSubSubField<scalar> deltaTSp0
140  (
141  other.mesh().sub(other.deltaTSp0Ptr_->internalField())
142  );
143 
144  deltaTSp0 = Zero;
145 
146  if (other.deltaTSp.valid()) deltaTSp0 = other.deltaTSp.S();
147  }
148 
149  if (notNull(other.S0Ptr_))
150  {
151  LagrangianSubSubField<Type> S0
152  (
153  other.mesh().sub(other.S0Ptr_->internalField())
154  );
155 
156  other.mesh().group() == LagrangianGroup::none ? S0 = Zero : S0 *= -1;
157 
158  if (other.Su.valid()) S0 += other.Su.S();
159  if (other.Sp.valid()) S0 += other.Sp.Su(other)->S();
160  }
161 
162  opClear(other);
163 }
164 
165 
166 template<class Type>
167 template<class OtherType>
169 (
170  const tmp<LagrangianEqn<OtherType>>& tOther
171 )
172 {
173  if (tOther.isTmp())
174  {
175  opFinalise(tOther.ref());
176  }
177 }
178 
179 
180 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
181 
182 template<class Type>
183 template<template<class> class PrimitiveField>
185 (
186  const word& name,
187  const tmp<LagrangianSubScalarField>& tDeltaT,
191 )
192 :
194  tDeltaT_(tDeltaT.valid() ? tDeltaT : tmp<LagrangianSubScalarField>()),
195  psiSubSubRef_(NullObjectNonConstRef<LagrangianSubSubField<Type>>()),
196  psiSubSub_(PsiRef<SubField>::ref(psi)),
197  psiSub_(PsiRef<Field>::ref(psi)),
198  deltaTSp0Ptr_(&deltaTSp0),
199  S0Ptr_(&S0),
200  deltaTSu(*this),
201  deltaTSp(*this),
202  Su(*this),
203  Sp(*this)
204 {}
205 
206 
207 template<class Type>
208 template<template<class> class PrimitiveField>
210 (
211  const word& name,
212  const LagrangianSubScalarField& deltaT,
216 )
217 :
219  (
220  name,
221  tmp<LagrangianSubScalarField>(deltaT),
222  psi,
223  deltaTSp0,
224  S0
225  )
226 {}
227 
228 
229 template<class Type>
230 template<template<class> class PrimitiveField>
232 (
233  const word& name,
237 )
238 :
239  LagrangianEqn(name, tmp<LagrangianSubScalarField>(), psi, deltaTSp0, S0)
240 {}
241 
242 
243 template<class Type>
244 template<template<class> class PrimitiveField>
246 (
247  const tmp<LagrangianSubScalarField>& tDeltaT,
251 )
252 :
253  LagrangianEqnBase(word::null, psi.mesh()),
254  tDeltaT_(tDeltaT.valid() ? tDeltaT : tmp<LagrangianSubScalarField>()),
255  psiSubSubRef_(NullObjectNonConstRef<LagrangianSubSubField<Type>>()),
256  psiSubSub_(PsiRef<SubField>::ref(psi)),
257  psiSub_(PsiRef<Field>::ref(psi)),
258  deltaTSp0Ptr_(&deltaTSp0),
259  S0Ptr_(&S0),
260  deltaTSu(*this),
261  deltaTSp(*this),
262  Su(*this),
263  Sp(*this)
264 {}
265 
266 
267 template<class Type>
268 template<template<class> class PrimitiveField>
270 (
271  const LagrangianSubScalarField& deltaT,
275 )
276 :
277  LagrangianEqn(tmp<LagrangianSubScalarField>(deltaT), psi, deltaTSp0, S0)
278 {}
279 
280 
281 template<class Type>
282 template<template<class> class PrimitiveField>
284 (
288 )
289 :
290  LagrangianEqn(tmp<LagrangianSubScalarField>(), psi, deltaTSp0, S0)
291 {}
292 
293 
294 template<class Type>
296 (
297  const tmp<LagrangianSubScalarField>& tDeltaT,
301 )
302 :
303  LagrangianEqnBase(psi.name() + "Eqn", psi.mesh()),
304  tDeltaT_(tDeltaT.valid() ? tDeltaT : tmp<LagrangianSubScalarField>()),
305  psiSubSubRef_(psi),
306  psiSubSub_(psi),
307  psiSub_(NullObjectRef<LagrangianSubField<Type>>()),
308  deltaTSp0Ptr_(&deltaTSp0),
309  S0Ptr_(&S0),
310  deltaTSu(*this),
311  deltaTSp(*this),
312  Su(*this),
313  Sp(*this)
314 {}
315 
316 
317 template<class Type>
319 (
320  const LagrangianSubScalarField& deltaT,
324 )
325 :
326  LagrangianEqn(tmp<LagrangianSubScalarField>(deltaT), psi, deltaTSp0, S0)
327 {}
328 
329 
330 template<class Type>
332 (
336 )
337 :
338  LagrangianEqn(tmp<LagrangianSubScalarField>(), psi, deltaTSp0, S0)
339 {}
340 
341 
342 template<class Type>
344 :
345  LagrangianEqnBase(word::null, mesh),
346  tDeltaT_(tmp<LagrangianSubScalarField>()),
347  psiSubSubRef_(NullObjectNonConstRef<LagrangianSubSubField<Type>>()),
348  psiSubSub_(NullObjectRef<LagrangianSubSubField<Type>>()),
349  psiSub_(NullObjectRef<LagrangianSubField<Type>>()),
350  deltaTSp0Ptr_(&NullObjectNonConstRef<LagrangianDynamicField<scalar>>()),
352  deltaTSu(*this),
353  deltaTSp(*this),
354  Su(*this),
355  Sp(*this)
356 {}
357 
358 
359 template<class Type>
361 :
362  LagrangianEqn(tmp<LagrangianEqn<Type>>(eqn))
363 {}
364 
365 
366 template<class Type>
368 :
369  LagrangianEqnBase(tEqn().name(), tEqn().mesh()),
370  tDeltaT_
371  (
372  tEqn().tDeltaT_.valid()
373  ? tmp<LagrangianSubScalarField>(tEqn().tDeltaT_, tEqn.isTmp())
375  ),
376  psiSubSubRef_(tEqn().psiSubSubRef_),
377  psiSubSub_(tEqn().psiSubSub_),
378  psiSub_(tEqn().psiSub_),
379  deltaTSp0Ptr_
380  (
381  tEqn.isTmp()
382  ? tEqn().deltaTSp0Ptr_
384  ),
385  S0Ptr_
386  (
387  tEqn.isTmp()
388  ? tEqn().S0Ptr_
390  ),
391  deltaTSu
392  (
393  tEqn.isTmp()
394  ? LagrangianCoeff<Type, false>(*this, tEqn.ref().deltaTSu, true)
395  : LagrangianCoeff<Type, false>(*this, tEqn().deltaTSu)
396  ),
397  deltaTSp
398  (
399  tEqn.isTmp()
400  ? LagrangianCoeff<scalar, true>(*this, tEqn.ref().deltaTSp, true)
401  : LagrangianCoeff<scalar, true>(*this, tEqn().deltaTSp)
402  ),
403  Su
404  (
405  tEqn.isTmp()
406  ? LagrangianCoeff<Type, false>(*this, tEqn.ref().Su, true)
407  : LagrangianCoeff<Type, false>(*this, tEqn().Su)
408  ),
409  Sp
410  (
411  tEqn.isTmp()
412  ? LagrangianSp<Type>(*this, tEqn.ref().Sp, true)
413  : LagrangianSp<Type>(*this, tEqn().Sp)
414  )
415 {
416  opClear(tEqn);
417  tEqn.clear();
418 }
419 
420 
421 template<class Type>
423 :
424  LagrangianEqnBase(eqn.name(), eqn.mesh()),
425  tDeltaT_(move(eqn.tDeltaT_)),
426  psiSubSubRef_(eqn.psiSubSubRef_),
427  psiSubSub_(eqn.psiSubSub_),
428  psiSub_(eqn.psiSub_),
429  deltaTSp0Ptr_(eqn.deltaTSp0Ptr_),
430  S0Ptr_(eqn.S0Ptr_),
431  deltaTSu(move(eqn.deltaTSu)),
432  deltaTSp(move(eqn.deltaTSp)),
433  Su(move(eqn.Su)),
434  Sp(move(eqn.Sp))
435 {
436  opClear(eqn);
437 }
438 
439 
440 template<class Type>
441 template<class EqOp>
443 (
444  const tmp<LagrangianEqn<Type>>& tA,
445  const tmp<LagrangianEqn<Type>>& tB,
446  const EqOp& eqOp
447 )
448 :
450  (
451  notNull(tA().psiSubSubRef_) && isNull(tB().psiSubSubRef_) ? tA().name()
452  : isNull(tA().psiSubSubRef_) && notNull(tB().psiSubSubRef_) ? tB().name()
453  : tA().name() == word::null ? tB().name()
454  : tB().name() == word::null ? tA().name()
455  : tA().name() == tB().name() ? tA().name()
456  : word::null,
457  tA().mesh()
458  ),
459  tDeltaT_
460  (
461  tA().tDeltaT_.valid()
462  ? tmp<LagrangianSubScalarField>(tA().tDeltaT_, tA.isTmp())
464  ),
465  psiSubSubRef_
466  (
467  notNull(tA().psiSubSubRef_) ? tA().psiSubSubRef_
468  : notNull(tB().psiSubSubRef_) ? tB().psiSubSubRef_
470  ),
471  psiSubSub_
472  (
473  notNull(tA().psiSubSub_) ? tA().psiSubSub_
474  : notNull(tB().psiSubSub_) ? tB().psiSubSub_
476  ),
477  psiSub_
478  (
479  notNull(tA().psiSub_) ? tA().psiSub_
480  : notNull(tB().psiSub_) ? tB().psiSub_
482  ),
483  deltaTSp0Ptr_
484  (
485  tA.isTmp()
486  ? tA().deltaTSp0Ptr_
488  ),
489  S0Ptr_
490  (
491  tA.isTmp()
492  ? tA().S0Ptr_
494  ),
495  deltaTSu
496  (
497  tA.isTmp()
498  ? LagrangianCoeff<Type, false>(*this, tA.ref().deltaTSu, true)
499  : LagrangianCoeff<Type, false>(*this, tA().deltaTSu)
500  ),
501  deltaTSp
502  (
503  tA.isTmp()
504  ? LagrangianCoeff<scalar, true>(*this, tA.ref().deltaTSp, true)
505  : LagrangianCoeff<scalar, true>(*this, tA().deltaTSp)
506  ),
507  Su
508  (
509  tA.isTmp()
510  ? LagrangianCoeff<Type, false>(*this, tA.ref().Su, true)
511  : LagrangianCoeff<Type, false>(*this, tA().Su)
512  ),
513  Sp
514  (
515  tA.isTmp()
516  ? LagrangianSp<Type>(*this, tA.ref().Sp, true)
517  : LagrangianSp<Type>(*this, tA().Sp)
518  )
519 {
520  preOpCheck(tA, tB);
521 
522  opDeltaT(tB);
523 
524  opClear(tA);
525  tA.clear();
526 
527  // Combine the coefficients
528  eqOp(*this, tB());
529 
530  // Copy/check the old-time pointers from/against the second equation
531  if (tB.isTmp())
532  {
533  if (notNull(tB().deltaTSp0Ptr_))
534  {
535  if (notNull(deltaTSp0Ptr_) && deltaTSp0Ptr_ != tB().deltaTSp0Ptr_)
536  {
538  << "Operating equations with different previous "
539  << "implicit time coefficients" << exit(FatalError);
540  }
541 
542  if (isNull(deltaTSp0Ptr_)) deltaTSp0Ptr_ = tB.ref().deltaTSp0Ptr_;
543  }
544 
545  if (notNull(tB().S0Ptr_))
546  {
547  if (notNull(S0Ptr_) && S0Ptr_ != tB().S0Ptr_)
548  {
550  << "Operating equations with different previous "
551  << "sources" << exit(FatalError);
552  }
553 
554  if (isNull(S0Ptr_)) S0Ptr_ = tB.ref().S0Ptr_;
555  }
556  }
557 
558  opClear(tB);
559  tB.clear();
560 }
561 
562 
563 template<class Type>
564 template<class EqOp, class TypeB>
566 (
567  const tmp<LagrangianEqn<Type>>& tA,
568  const tmp<LagrangianEqn<TypeB>>& tB,
569  const EqOp& eqOp
570 )
571 :
572  LagrangianEqn(tA)
573 {
574  preOpCheck(tmp<LagrangianEqn<Type>>(*this), tB);
575 
576  opDeltaT(tB);
577 
578  // Ignore the old-time pointers in the second equation. If they are of a
579  // different type then they cannot relate to this equation.
580 
581  // Combine the coefficients
582  eqOp(*this, tB());
583 
584  opClear(tB);
585  tB.clear();
586 }
587 
588 
589 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
590 
591 template<class Type>
593 {
594  opFinalise(*this);
595 }
596 
597 
598 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
599 
600 template<class Type>
602 (
603  const LagrangianEqn<Type>& eqn
604 )
605 {
606  return
608  (
609  notNull(eqn.psiSubSub_)
610  ? new LagrangianEqn<Type>(eqn.psiSubSub_)
611  : new LagrangianEqn<Type>(eqn.psiSub_)
612  );
613 }
614 
615 
616 template<class Type>
619 {
620  if (notNull(psiSubSub_)) return psiSubSub_;
621 
622  if (notNull(psiSub_)) return toSubField(psiSub_);
623 
625  << "Requested field from field-less equation"
626  << exit(FatalError);
627 
629 }
630 
631 
632 template<class Type>
634 {
635  if (notNull(psiSubSub_)) return psiSubSub_.name();
636 
637  if (notNull(psiSub_)) return psiSub_.name();
638 
639  return word::null;
640 }
641 
642 
643 template<class Type>
645 {
646  if (notNull(psiSubSub_)) return psiSubSub_.group();
647 
648  if (notNull(psiSub_)) return psiSub_.group();
649 
650  return word::null;
651 }
652 
653 
654 template<class Type>
655 template<template<class> class PrimitiveField>
657 (
659 ) const
660 {
661  const regIOobject& otherPsiIo = otherPsi;
662 
663  if (notNull(psiSubSub_))
664  {
665  return &otherPsiIo == &static_cast<const regIOobject&>(psiSubSub_);
666  }
667 
668  if (notNull(psiSub_))
669  {
670  return &otherPsiIo == &static_cast<const regIOobject&>(psiSub_);
671  }
672 
673  return false;
674 }
675 
676 
677 template<class Type>
679 {
680  return deltaTSu.valid() || deltaTSp.valid() || Su.valid() || Sp.valid();
681 }
682 
683 
684 template<class Type>
687 {
688  if (Su.valid() && !tDeltaT_.valid())
689  {
691  << "Cannot evaluate equation " << name_ << " for field "
692  << psiName() << " without a time-step" << exit(FatalError);
693  }
694 
696  (
698  );
699 
700  tResult.ref() += Su;
701  if (tDeltaT_.valid()) tResult.ref() *= tDeltaT_();
702  tResult.ref() += deltaTSu;
703 
704  return tResult;
705 }
706 
707 
708 template<class Type>
710 {
711  if (Sp.valid() && !tDeltaT_.valid())
712  {
714  << "Cannot evaluate equation " << name_ << " for field "
715  << psiName() << " without a time-step" << exit(FatalError);
716  }
717 
718  tmp<LagrangianSp<Type>> tResult(new LagrangianSp<Type>(*this));
719 
720  tResult.ref() += Sp;
721  if (tDeltaT_.valid()) tResult.ref() *= tDeltaT_();
722  tResult.ref() += deltaTSp;
723 
724  return tResult;
725 }
726 
727 
728 template<class Type>
731 {
733 
734  if ((Su.valid() || tSpH().valid()) && !tDeltaT_.valid())
735  {
737  << "Cannot evaluate equation " << name_ << " for field "
738  << psiName() << " without a time-step" << exit(FatalError);
739  }
740 
742  (
744  );
745 
746  tResult.ref() += Su;
747  tResult.ref() += tSpH;
748  if (tDeltaT_.valid()) tResult.ref() *= tDeltaT_();
749  tResult.ref() += deltaTSu;
750 
751  return tResult;
752 }
753 
754 
755 template<class Type>
758 {
760 
761  if (tSpA().valid() && !tDeltaT_.valid())
762  {
764  << "Cannot evaluate equation " << name_ << " for field "
765  << psiName() << " without a time-step" << exit(FatalError);
766  }
767 
769  (
771  );
772 
773  tResult.ref() += Sp.A();
774  if (tDeltaT_.valid()) tResult.ref() *= tDeltaT_();
775  tResult.ref() += deltaTSp;
776 
777  return tResult;
778 }
779 
780 
781 template<class Type>
782 void Foam::LagrangianEqn<Type>::solve(const bool final)
783 {
784  if (!tDeltaT_.valid())
785  {
787  << "Cannot solve equation " << name_ << " for field "
788  << psiName() << " without a time-step" << exit(FatalError);
789  }
790 
791  if (isNull(psiSubSubRef_))
792  {
794  << "Cannot solve equation " << name_ << " for constant field "
795  << psiName() << exit(FatalError);
796  }
797 
798  if (!deltaTSp.valid() && !Sp.valid())
799  {
801  << "Cannot solve equation " << name_ << " for field "
802  << psiName() << " with no diagonal" << exit(FatalError);
803  }
804 
805  if (!deltaTSu.valid() && !Su.valid())
806  {
807  psiSubSubRef_ = Zero;
808  return;
809  }
810 
811  psiSubSubRef_ = - (allSu()()/allSp()());
812 
813  if (!final)
814  {
815  deltaTSp0Ptr_ = NullObjectPtr<LagrangianDynamicField<scalar>>();
816  S0Ptr_ = NullObjectPtr<LagrangianDynamicField<Type>>();
817  }
818 }
819 
820 
821 // * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
822 
823 template<class Type>
824 template<class OtherType>
826 (
827  const LagrangianEqn<OtherType>& other
828 )
829 {
830  deltaTSu += other.deltaTSu;
831  deltaTSp += other.deltaTSp;
832  Su += other.Su;
833  Sp += other.Sp;
834 }
835 
836 
837 template<class Type>
838 template<class OtherType>
840 (
841  const tmp<LagrangianEqn<OtherType>>& tOther
842 )
843 {
844  operator+=(tOther());
845  tOther.clear();
846 }
847 
848 
849 template<class Type>
850 template<class OtherType>
852 (
853  const LagrangianEqn<OtherType>& other
854 )
855 {
856  deltaTSu -= other.deltaTSu;
857  deltaTSp -= other.deltaTSp;
858  Su -= other.Su;
859  Sp -= other.Sp;
860 }
861 
862 
863 template<class Type>
864 template<class OtherType>
866 (
867  const tmp<LagrangianEqn<OtherType>>& tOther
868 )
869 {
870  operator-=(tOther());
871  tOther.clear();
872 }
873 
874 
875 template<class Type>
876 template<template<class> class PrimitiveField>
878 (
880 )
881 {
882  opFinalise(*this);
883  deltaTSu *= S;
884  deltaTSp *= S;
885  Su *= S;
886  Sp *= S;
887 }
888 
889 
890 template<class Type>
891 template<template<class> class PrimitiveField>
893 (
895 )
896 {
897  this->operator*=(tS());
898  tS.clear();
899 }
900 
901 
902 template<class Type>
904 {
905  opFinalise(*this);
906  deltaTSu *= dt;
907  deltaTSp *= dt;
908  Su *= dt;
909  Sp *= dt;
910 }
911 
912 
913 template<class Type>
915 {
916  opFinalise(*this);
917  deltaTSu *= z;
918  deltaTSp *= z;
919  Su *= z;
920  Sp *= z;
921 }
922 
923 
924 template<class Type>
925 template<template<class> class PrimitiveField>
927 (
929 )
930 {
931  opFinalise(*this);
932  deltaTSu /= S;
933  deltaTSp /= S;
934  Su /= S;
935  Sp /= S;
936 }
937 
938 
939 template<class Type>
940 template<template<class> class PrimitiveField>
942 (
944 )
945 {
946  this->operator/=(tS());
947  tS.clear();
948 }
949 
950 
951 template<class Type>
953 {
954  opFinalise(*this);
955  deltaTSu /= dt;
956  deltaTSp /= dt;
957  Su /= dt;
958  Sp /= dt;
959 }
960 
961 
962 // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
963 
964 template<class Type>
966 (
967  const LagrangianEqn<Type>& eqn
968 )
969 {
970  return - tmp<LagrangianEqn<Type>>(eqn);
971 }
972 
973 
974 template<class Type>
976 (
977  const tmp<LagrangianEqn<Type>>& tEqn
978 )
979 {
980  tmp<LagrangianEqn<Type>> tResult(tEqn, true);
981  tResult.ref().deltaTSu.negate();
982  tResult.ref().deltaTSp.negate();
983  tResult.ref().Su.negate();
984  tResult.ref().Sp.negate();
985  return tResult;
986 }
987 
988 
989 #define LAGRANGIAN_EQN_EQN_OPERATOR(Op, EqOp) \
990  \
991  template<class Type, class TypeB> \
992  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
993  ( \
994  const LagrangianEqn<Type>& a, \
995  const LagrangianEqn<TypeB>& b \
996  ) \
997  { \
998  return tmp<LagrangianEqn<Type>>(a) Op tmp<LagrangianEqn<TypeB>>(b); \
999  }; \
1000  \
1001  template<class Type, class TypeB> \
1002  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1003  ( \
1004  const tmp<LagrangianEqn<Type>>& tA, \
1005  const LagrangianEqn<TypeB>& b \
1006  ) \
1007  { \
1008  return tA Op tmp<LagrangianEqn<TypeB>>(b); \
1009  }; \
1010  \
1011  template<class Type, class TypeB> \
1012  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1013  ( \
1014  const tmp<LagrangianEqn<Type>>& tA, \
1015  const tmp<LagrangianEqn<TypeB>>& tB \
1016  ) \
1017  { \
1018  return \
1019  tmp<LagrangianEqn<Type>> \
1020  ( \
1021  new LagrangianEqn<Type> \
1022  ( \
1023  tA, \
1024  tB, \
1025  [] \
1026  ( \
1027  LagrangianEqn<Type>& a, \
1028  const LagrangianEqn<TypeB>& b \
1029  ) \
1030  { \
1031  a EqOp b; \
1032  } \
1033  ) \
1034  ); \
1035  } \
1036  \
1037  template<class Type, class TypeB> \
1038  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1039  ( \
1040  const LagrangianEqn<Type>& a, \
1041  const tmp<LagrangianEqn<TypeB>>& tB \
1042  ) \
1043  { \
1044  return tmp<LagrangianEqn<Type>>(a) Op tB; \
1045  }
1046 
1047 #define LAGRANGIAN_COMMUTATIVE_EQN_EQN_OPERATOR(Op, EqOp) \
1048  \
1049  LAGRANGIAN_EQN_EQN_OPERATOR(Op, EqOp) \
1050  \
1051  template<class Type> \
1052  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1053  ( \
1054  const LagrangianEqn<Type>& a, \
1055  const tmp<LagrangianEqn<Type>>& tB \
1056  ) \
1057  { \
1058  return tB Op a; \
1059  }
1060 
1062 
1064 
1066 
1067 #undef LAGRANGIAN_EQN_EQN_OPERATOR
1068 #undef LAGRANGIAN_COMMUTATIVE_EQN_EQN_OPERATOR
1069 
1070 
1071 #define LAGRANGIAN_EQN_FIELD_OPERATOR(Op, EqOp, LagrangianSubField) \
1072  \
1073  template<class Type> \
1074  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1075  ( \
1076  const LagrangianEqn<Type>& eqn, \
1077  const LagrangianSubField<Type>& field \
1078  ) \
1079  { \
1080  tmp<LagrangianEqn<Type>> tResult(new LagrangianEqn<Type>(eqn)); \
1081  tResult.ref().Su EqOp field; \
1082  return tResult; \
1083  } \
1084  \
1085  template<class Type> \
1086  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1087  ( \
1088  const tmp<LagrangianEqn<Type>>& tEqn, \
1089  const LagrangianSubField<Type>& field \
1090  ) \
1091  { \
1092  tmp<LagrangianEqn<Type>> tResult(tEqn, true); \
1093  tResult.ref().Su EqOp field; \
1094  return tResult; \
1095  } \
1096  \
1097  template<class Type> \
1098  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1099  ( \
1100  const tmp<LagrangianEqn<Type>>& tEqn, \
1101  const tmp<LagrangianSubField<Type>>& tField \
1102  ) \
1103  { \
1104  tmp<LagrangianEqn<Type>> tResult(tEqn, true); \
1105  tResult.ref().Su EqOp tField; \
1106  return tResult; \
1107  } \
1108  \
1109  template<class Type> \
1110  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1111  ( \
1112  const LagrangianEqn<Type>& eqn, \
1113  const tmp<LagrangianSubField<Type>>& tField \
1114  ) \
1115  { \
1116  tmp<LagrangianEqn<Type>> tResult(new LagrangianEqn<Type>(eqn)); \
1117  tResult.ref().Su EqOp tField; \
1118  return tResult; \
1119  }
1120 
1121 #define LAGRANGIAN_FIELD_EQN_OPERATOR(Op, EqOp, LagrangianSubField) \
1122  \
1123  template<class Type> \
1124  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1125  ( \
1126  const LagrangianSubField<Type>& field, \
1127  const LagrangianEqn<Type>& eqn \
1128  ) \
1129  { \
1130  tmp<LagrangianEqn<Type>> tResult = \
1131  LagrangianEqn<Type>::NewEmpty(eqn); \
1132  tResult.ref() += field; \
1133  tResult.ref() EqOp eqn; \
1134  return tResult; \
1135  } \
1136  \
1137  template<class Type> \
1138  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1139  ( \
1140  const LagrangianSubField<Type>& field, \
1141  const tmp<LagrangianEqn<Type>>& tEqn \
1142  ) \
1143  { \
1144  tmp<LagrangianEqn<Type>> tResult = \
1145  LagrangianEqn<Type>::NewEmpty(tEqn()); \
1146  tResult.ref() += field; \
1147  tResult.ref() EqOp tEqn; \
1148  return tResult; \
1149  } \
1150  \
1151  template<class Type> \
1152  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1153  ( \
1154  const tmp<LagrangianSubField<Type>>& tField, \
1155  const tmp<LagrangianEqn<Type>>& tEqn \
1156  ) \
1157  { \
1158  tmp<LagrangianEqn<Type>> tResult = \
1159  LagrangianEqn<Type>::NewEmpty(tEqn()); \
1160  tResult.ref() += tField; \
1161  tResult.ref() EqOp tEqn; \
1162  return tResult; \
1163  } \
1164  \
1165  template<class Type> \
1166  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1167  ( \
1168  const tmp<LagrangianSubField<Type>>& tField, \
1169  const LagrangianEqn<Type>& eqn \
1170  ) \
1171  { \
1172  tmp<LagrangianEqn<Type>> tResult = \
1173  LagrangianEqn<Type>::NewEmpty(eqn); \
1174  tResult.ref() += tField; \
1175  tResult.ref() EqOp eqn; \
1176  return tResult; \
1177  }
1178 
1179 //- Addition
1184 
1185 //- Subtraction
1190 
1191 //- Set-equal-to
1196 
1197 #undef LAGRANGIAN_EQN_FIELD_OPERATOR
1198 #undef LAGRANGIAN_FIELD_EQN_OPERATOR
1199 
1200 
1201 #define LAGRANGIAN_EQN_SCALAR_FIELD_OPERATOR(Op, EqOp, LagrangianSubField) \
1202  \
1203  template<class Type> \
1204  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1205  ( \
1206  const LagrangianEqn<Type>& eqn, \
1207  const LagrangianSubField<scalar>& field \
1208  ) \
1209  { \
1210  tmp<LagrangianEqn<Type>> tResult(new LagrangianEqn<Type>(eqn)); \
1211  tResult.ref() EqOp field; \
1212  return tResult; \
1213  } \
1214  \
1215  template<class Type> \
1216  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1217  ( \
1218  const tmp<LagrangianEqn<Type>>& tEqn, \
1219  const LagrangianSubField<scalar>& field \
1220  ) \
1221  { \
1222  tmp<LagrangianEqn<Type>> tResult(tEqn, true); \
1223  tResult.ref() EqOp field; \
1224  return tResult; \
1225  } \
1226  \
1227  template<class Type> \
1228  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1229  ( \
1230  const tmp<LagrangianEqn<Type>>& tEqn, \
1231  const tmp<LagrangianSubField<scalar>>& tField \
1232  ) \
1233  { \
1234  tmp<LagrangianEqn<Type>> tResult(tEqn, true); \
1235  tResult.ref() EqOp tField; \
1236  return tResult; \
1237  } \
1238  \
1239  template<class Type> \
1240  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1241  ( \
1242  const LagrangianEqn<Type>& eqn, \
1243  const tmp<LagrangianSubField<scalar>>& tField \
1244  ) \
1245  { \
1246  tmp<LagrangianEqn<Type>> tResult(new LagrangianEqn<Type>(eqn)); \
1247  tResult.ref() EqOp tField; \
1248  return tResult; \
1249  }
1250 
1251 #define LAGRANGIAN_COMMUTATIVE_SCALAR_FIELD_EQN_OPERATOR(Op,LagrangianSubField)\
1252  \
1253  template<class Type> \
1254  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1255  ( \
1256  const LagrangianSubField<scalar>& field, \
1257  const LagrangianEqn<Type>& eqn \
1258  ) \
1259  { \
1260  return eqn Op field; \
1261  } \
1262  \
1263  template<class Type> \
1264  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1265  ( \
1266  const LagrangianSubField<scalar>& field, \
1267  const tmp<LagrangianEqn<Type>>& tEqn \
1268  ) \
1269  { \
1270  return tEqn Op field; \
1271  } \
1272  \
1273  template<class Type> \
1274  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1275  ( \
1276  const tmp<LagrangianSubField<scalar>>& tField, \
1277  const tmp<LagrangianEqn<Type>>& tEqn \
1278  ) \
1279  { \
1280  return tEqn Op tField; \
1281  } \
1282  \
1283  template<class Type> \
1284  Foam::tmp<Foam::LagrangianEqn<Type>> Foam::operator Op \
1285  ( \
1286  const tmp<LagrangianSubField<scalar>>& tField, \
1287  const LagrangianEqn<Type>& eqn \
1288  ) \
1289  { \
1290  return eqn Op tField; \
1291  }
1292 
1293 //- Multiplication
1298 
1299 //- Division
1302 
1303 #undef LAGRANGIAN_EQN_SCALAR_FIELD_OPERATOR
1304 #undef LAGRANGIAN_COMMUTATIVE_SCALAR_FIELD_EQN_OPERATOR
1305 
1306 // ************************************************************************* //
#define LAGRANGIAN_EQN_EQN_OPERATOR(Op, EqOp)
#define LAGRANGIAN_COMMUTATIVE_SCALAR_FIELD_EQN_OPERATOR(Op, LagrangianSubField)
#define LAGRANGIAN_COMMUTATIVE_EQN_EQN_OPERATOR(Op, EqOp)
#define LAGRANGIAN_EQN_SCALAR_FIELD_OPERATOR(Op, EqOp, LagrangianSubField)
#define LAGRANGIAN_EQN_FIELD_OPERATOR(Op, EqOp, LagrangianSubField)
#define LAGRANGIAN_FIELD_EQN_OPERATOR(Op, EqOp, LagrangianSubField)
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Pre-declare SubField and related Field type.
Definition: Field.H:83
Generic GeometricField class.
Class to store a coefficient of a Lagrangian equation.
Non-templated base class for Lagrangian equations.
This class stores the coefficients of a Lagrangian equation, and facilitates solving that equation an...
Definition: LagrangianEqn.H:56
word psiGroup() const
Return the field group.
void solve(const bool final)
Solve.
tmp< LagrangianSp< Type > > allSp() const
Return the combined time and non-time implicit coefficient.
bool valid() const
Determine whether this matrix has any valid coefficients.
bool isPsi(const LagrangianSubField< Type, PrimitiveField > &) const
Return whether the given field is that of the equation.
tmp< LagrangianCoeff< scalar, true > > allDiagonalSp() const
Return the combined time and non-time implicit diagonal.
~LagrangianEqn()
Destructor.
friend class LagrangianEqn
Declare friendship with Lagrangian equations of different types.
void operator/=(const LagrangianSubField< scalar, PrimitiveField > &)
Division assignment.
tmp< LagrangianCoeff< Type, false > > allDiagonalSu() const
Return the combined time and non-time explicit diagonal.
tmp< LagrangianSubSubField< Type > > psi() const
Return the field.
void operator*=(const LagrangianSubField< scalar, PrimitiveField > &)
Multiply assignment.
static tmp< LagrangianEqn< Type > > NewEmpty(const LagrangianEqn< Type > &)
Construct from another equation, with empty coefficients.
LagrangianCoeff< Type, false > deltaTSu
Explicit time-coefficient.
const word & psiName() const
Return the field name.
tmp< LagrangianCoeff< Type, false > > allSu() const
Return the combined time and non-time explicit coefficient.
Wrapper around LagrangianCoeff to specialise for the implicit coefficient. Trivial at present....
Definition: LagrangianSp.H:71
Mesh that relates to a sub-section of a Lagrangian mesh. This is used to construct fields that relate...
Pre-declare related SubField type.
Definition: SubField.H:63
Definition: ops.H:70
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:55
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
A class for handling words, derived from string.
Definition: word.H:63
static const word null
An empty word.
Definition: word.H:78
A class representing the concept of 0 used to avoid unnecessary manipulations for objects that are kn...
Definition: zero.H:50
trAU ref().rename("rAU")
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
const volScalarField & psi
bool valid(const PtrList< ModelType > &l)
tmp< VolField< Type > > Su(const VolField< Type > &su, const VolField< Type > &vf)
Definition: fvcSup.C:44
tmp< VolField< Type > > Sp(const volScalarField &sp, const VolField< Type > &vf)
Definition: fvcSup.C:67
tmp< fvMatrix< Type > > S(const Pair< tmp< volScalarField::Internal >> &, const VolField< Type > &)
const unitSet none
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const zero Zero
Definition: zero.H:97
DimensionedField< Type, LagrangianSubMesh, PrimitiveField > LagrangianSubField
DimensionedField< Type, LagrangianSubMesh, SubField > LagrangianSubSubField
void operator*=(Other &, const oneOrTmp< Type > &)
Multiply-assign with an object.
Definition: oneOrTmpI.H:168
bool notNull(const T &t)
Return true if t is not a reference to the nullObject of type T.
Definition: nullObjectI.H:64
T * NullObjectPtr()
Return pointer to the nullObject of type T.
Definition: nullObjectI.H:45
const T & NullObjectRef()
Return const reference to the nullObject of type T.
Definition: nullObjectI.H:27
T & NullObjectNonConstRef()
Return non-const reference to the nullObject of type T.
Definition: nullObjectI.H:33
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
bool isNull(const T &t)
Return true if t is a reference to the nullObject of type T.
Definition: nullObjectI.H:58
error FatalError
void operator+=(fvMatrix< Type > &fvEqn, const CarrierEqn< Type > &cEqn)
Add to a finite-volume equation.
Definition: CarrierEqn.C:271
void operator-=(fvMatrix< Type > &fvEqn, const CarrierEqn< Type > &cEqn)
Subtract from a finite-volume equation.
Definition: CarrierEqn.C:299
tmp< DimensionedField< Type, GeoMesh, SubField > > toSubField(const DimensionedField< Type, GeoMesh, Field > &)
Return a temporary sub-field from a reference to a field.
#define EqOp(opName, op)
Definition: ops.H:46
Functions to cast/convert dimensioned field references and temporaries based on a primitive field to ...