GeometricFieldExpression.H
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) 2024,2025 M. Janssens
9  Copyright (C) 2025 OpenCFD Ltd.
10  Copyright (C) 2026 Keysight Technologies
11 -------------------------------------------------------------------------------
12 License
13  This file is part of OpenFOAM.
14 
15  OpenFOAM is free software: you can redistribute it and/or modify it
16  under the terms of the GNU General Public License as published by
17  the Free Software Foundation, either version 3 of the License, or
18  (at your option) any later version.
19 
20  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
21  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  for more details.
24 
25  You should have received a copy of the GNU General Public License
26  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
27 
28 InNamespace
29  Foam::Expression
30 
31 Description
32  Expression templates for GeometricFields
33 
34 SourceFiles
35  GeometricFieldExpression.H
36 
37 \*---------------------------------------------------------------------------*/
38 
39 #ifndef Foam_GeometricFieldExpression_H
40 #define Foam_GeometricFieldExpression_H
41 
42 #include "ListExpression.H"
43 #include "orientedType.H"
44 #include "pointMesh.H"
45 
46 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
47 
48 namespace Foam
49 {
50 namespace Expression
51 {
52 
53 // Forward Declarations
54 template<class GeoField> class UniformGeometricFieldWrap2;
55 
56 /*---------------------------------------------------------------------------*\
57  Class GeometricFieldExpression Declaration
58 \*---------------------------------------------------------------------------*/
59 
60 //- Expression of GeometricField
61 template
62 <
63  typename E,
64  typename IntExpr,
65  typename UncoupledPatchExpr,
66  typename CoupledPatchExpr,
67  typename Type
68 >
70 {
71 protected:
72 
74  const orientedType oriented_;
75 
76 public:
77  static constexpr bool is_leaf = false;
78 
80  (
81  const dimensionSet& dimensions,
83  )
84  :
87  {
88  //Pout<< "GeometricFieldExpression :" << nl
89  // << " E : " << error::demangle<E>() << nl
90  // << " IntExpr : " << error::demangle<IntExpr>() << nl
91  // << " dimensions : " << dimensions_ << nl
92  // << " oriented : " << oriented_ << nl
93  // << endl;
94  }
95 
96  // TBD. Do we still need this? Is faster than always going through
97  // internalField() though.
98  Type operator[](const label i) const
99  {
100  // Delegation to the actual expression type. This avoids dynamic
101  // polymorphism (a.k.a. virtual functions in C++)
102  return static_cast<E const&>(*this)[i];
103  }
104  auto size() const noexcept { return static_cast<const E&>(*this).size(); }
105 
106  const dimensionSet& dimensions() const noexcept
107  {
108  return dimensions_;
109  }
110 
111  const orientedType& oriented() const noexcept
112  {
113  return oriented_;
114  }
115 
116  IntExpr internalField() const
117  {
118  return static_cast<const E&>(*this).internalField();
119  }
120 
121  IntExpr internalField()
122  {
123  return static_cast<E&>(*this).internalField();
124  }
125 
126  UncoupledPatchExpr patchField(const label i)
127  {
128  return static_cast<E&>(*this).patchField(i);
129  }
130 
131  UncoupledPatchExpr patchField(const label i) const
132  {
133  return static_cast<const E&>(*this).patchField(i);
134  }
135 
136  CoupledPatchExpr coupledPatchField(const label i)
137  {
138  return static_cast<E&>(*this).coupledPatchField(i);
139  }
140 
141  CoupledPatchExpr coupledPatchField(const label i) const
142  {
143  return static_cast<const E&>(*this).coupledPatchField(i);
144  }
146  template<class Op>
147  auto access(const Op& cop, const label i) const
148  {
149  return static_cast<const E&>(*this).access(cop, i);
150  }
151 
152  //- Helper to evaluate a GeometricField
153  template<class GeoField>
154  GeoField& evaluate(GeoField& fld, const bool force = false) const
155  {
156  constexpr bool is_pointField =
157  std::is_same_v<pointMesh, typename GeoField::Mesh>;
158 
159  fld.dimensions() = this->dimensions();
160  fld.oriented() = this->oriented();
161 
162  assert(fld.size() == this->size());
163  typedef typename GeoField::value_type ActualType;
164  ListRefWrap<ActualType> wfld(fld.internalFieldRef(), internalField());
165 
166  // Do boundary field
167  typedef Field<ActualType> FieldType;
168  auto& bfld = fld.boundaryFieldRef();
169  const label n = bfld.size();
170 #if defined(__STDPAR__)
171  constexpr bool foam_offload = true;
172 #else
173  constexpr bool foam_offload = false;
174 #endif
175  if constexpr (foam_offload)
176  {
177  // Wrap multiple containers into single container so there is only
178  // a single kernel. Looking up individual container is fast enough.
179 
180  auto do_something = [](auto& data, label& i, auto& pfld)
181  {
182  if constexpr (is_pointField)
183  {
184  if (auto* vp = isA_constCast<FieldType>(pfld))
185  {
186  data[i++] = vp;
187  }
188  }
189  else
190  {
191  data[i++] = &static_cast<FieldType&>(pfld);
192  }
193  };
194 
195  // Note: avoid calling isA for pointFields
197  (
198  fld.boundaryFieldRef(),
199  do_something
200  );
201 
202  std::vector<UncoupledPatchExpr> unc_patchExpr;
203  std::vector<CoupledPatchExpr> cou_patchExpr;
204  std::vector<int> coupledID;
205  std::vector<int> uncoupledID;
206 
207  // Assume most patches are uncoupled
208  unc_patchExpr.reserve(n);
209  uncoupledID.reserve(n);
210 
211  for (label i = 0; i < n; ++i)
212  {
213  auto& pfld = bfld[i];
214  if (force || pfld.assignable())
215  {
216  if (pfld.coupled())
217  {
218  // Get patch expression
219  const auto patchExpr = this->coupledPatchField(i);
220  cou_patchExpr.emplace_back(patchExpr);
221  coupledID.emplace_back(i);
222  }
223  else
224  {
225  const auto patchExpr = this->patchField(i);
226  unc_patchExpr.emplace_back(patchExpr);
227  uncoupledID.emplace_back(i);
228  }
229  }
230  }
231 
232  ListsRefWrap<UncoupledPatchExpr> uncpatchExprExpression
233  (
234  unc_patchExpr
235  );
236  ListsRefWrap<CoupledPatchExpr> coupatchExprExpression
237  (
238  cou_patchExpr
239  );
240 
241  // Evaluate
242 
243  coupatchExprExpression.evaluate(expr, coupledID);
244  uncpatchExprExpression.evaluate(expr, uncoupledID);
245  }
246  else
247  {
248  // Patch by patch evaluation
249  for (label i = 0; i < n; ++i)
250  {
251  auto& pfld = bfld[i];
252  if (force || pfld.assignable())
253  {
254  if (pfld.coupled())
255  {
256  // Get patch expression
257  const auto patchExpr = this->coupledPatchField(i);
258 
259  if constexpr (is_pointField)
260  {
261  if (auto* vp = isA_constCast<FieldType>(pfld))
262  {
263  patchExpr.evaluate(*vp);
264  }
265  }
266  else
267  {
268  patchExpr.evaluate(pfld);
269  }
270  }
271  else
272  {
273  // Get patch expression
274  const auto patchExpr = this->patchField(i);
275 
276  if constexpr (is_pointField)
277  {
278  if (auto* vp = isA_constCast<FieldType>(pfld))
279  {
280  patchExpr.evaluate(*vp);
281  }
282  }
283  else
284  {
285  patchExpr.evaluate(pfld);
286  }
287  }
288  }
289  }
290  }
291  fld.correctLocalBoundaryConditions();
292  return fld;
293  }
294 };
295 
296 
297 /*---------------------------------------------------------------------------*\
298  Class GeometricFieldRefWrap Declaration
299 \*---------------------------------------------------------------------------*/
300 
301 //- Expression wrap of non-const reference to GeometricField
302 template<class GeoField>
303 class GeometricFieldRefWrap
304 :
306  <
307  GeometricFieldRefWrap<GeoField>,
308  ListRefWrap<typename GeoField::value_type>,
309  ListRefWrap<typename GeoField::value_type>,
310  ListTmpWrap<Field<typename GeoField::value_type>>,
311  typename GeoField::value_type
312  >
313 {
314 public:
315 
316  static constexpr bool is_leaf = false; //true;
317 
318  //- True if GeoField is associated with a pointMesh
319  static constexpr bool is_pointField =
320  std::is_same_v<pointMesh, typename GeoField::Mesh>;
321 
322  //- The GeometricField type
323  typedef GeoField this_type;
324 
325  //- Type to return for internal field
326  typedef typename GeoField::value_type value_type;
327 
328  //- Type to return for patchField
332 
333 
334 private:
335 
336  this_type& elems_;
337 
338 
339 public:
341  //- Copy construct
343  :
345  <
346  GeometricFieldRefWrap<GeoField>,
347  IntExpr,
350  value_type
351  >
352  (
353  elems.dimensions(),
354  elems.oriented()
355  ),
356  elems_(elems)
357  {}
358 
359  //- Move construct
361  :
363  <
364  GeometricFieldRefWrap<GeoField>,
365  IntExpr,
368  value_type
369  >
370  (
371  elems.dimensions(),
372  elems.oriented()
373  ),
374  elems_(elems)
375  {}
376 
377  // Construct from ListExpression, forcing its evaluation.
378  template<typename E>
380  (
381  this_type& elems,
383  <
384  E,
385  typename E::IntExpr,
386  typename E::UncoupledPatchExpr,
387  typename E::CoupledPatchExpr,
388  typename E::value_type
389  >& expr
390  )
391  :
393  <
395  IntExpr,
398  value_type
399  >
400  (
401  elems.dimensions(),
402  elems.oriented()
403  ),
404  elems_(elems)
405  {
406  expr.evaluate(elems_);
407  }
408 
409  //- Assignment
410  template<typename E>
411  void operator=
412  (
414  <
415  E,
416  typename E::IntExpr,
417  typename E::UncoupledPatchExpr,
418  typename E::CoupledPatchExpr,
419  typename E::value_type
420  >& expr
421  )
422  {
423  expr.evaluate(elems_);
424  }
425 
426  //- Evaluate and return as GeoField. Rename to evaluate to make it clear
427  //- it takes time? Or leave as indexing for convenience?
428  template<typename E>
430  (
432  <
433  E,
434  typename E::IntExpr,
435  typename E::UncoupledPatchExpr,
436  typename E::CoupledPatchExpr,
437  typename E::value_type
438  >& expr
439  )
440  {
441  return expr.evaluate(elems_);
442  }
443 
444  value_type operator[](const label i) const
445  {
446  return elems_[i];
447  }
449  value_type& operator[](const label i)
450  {
451  return elems_[i];
452  }
453 
454  auto size() const noexcept
455  {
456  return elems_.size();
457  }
458 
460  {
461  auto& fld = elems_.internalFieldRef();
462  return IntExpr(fld.size(), fld);
463  }
464 
465  IntExpr internalField() const
466  {
467  auto& fld = elems_.internalField();
468  return IntExpr(fld.size(), fld);
469  }
470 
471  UncoupledPatchExpr patchField(const label i)
472  {
473  auto& fld = elems_.boundaryFieldRef()[i];
474 
475  if constexpr (is_pointField)
476  {
478  {
479  return UncoupledPatchExpr(vp->size(), *vp);
480  }
481  else
482  {
484  }
485  }
486  else
487  {
488  return UncoupledPatchExpr(fld.size(), fld);
489  }
490  }
491 
492  UncoupledPatchExpr patchField(const label i) const
493  {
494  const auto& fld = elems_.boundaryField()[i];
495 
496  if constexpr (is_pointField)
497  {
498  if (const auto* vp = isA<Field<value_type>>(fld))
499  {
500  return UncoupledPatchExpr(vp->size(), *vp);
501  }
502  else
503  {
505  }
506  }
507  else
508  {
509  return UncoupledPatchExpr(fld.size(), fld);
510  }
511  }
512 
513  CoupledPatchExpr coupledPatchField(const label i)
514  {
515  auto& fld = elems_.boundaryFieldRef()[i];
516 
517  if constexpr (is_pointField)
518  {
519  if (auto* vp = isA_constCast<Field<value_type>>(fld))
520  {
521  return CoupledPatchExpr(*vp);
522  }
523  else
524  {
526  }
527  }
528  else
529  {
530  return CoupledPatchExpr(fld);
531  }
532  }
533 
534  CoupledPatchExpr coupledPatchField(const label i) const
535  {
536  const auto& fld = elems_.boundaryField()[i];
537 
538  if constexpr (is_pointField)
539  {
540  if (const auto* vp = isA<Field<value_type>>(fld))
541  {
542  //return CoupledPatchExpr(vp->size(), *vp);
543  return CoupledPatchExpr(*vp);
544  }
545  else
546  {
547  //return CoupledPatchExpr(0, List<value_type>::null());
549  }
550  }
551  else
552  {
553  //return UncoupledPatchExpr(fld.size(), fld);
554  return CoupledPatchExpr(fld);
555  }
556  }
557 
558  template<class AccessOp>
559  auto access(const AccessOp& cop, const label i) const
560  {
561  return cop(elems_, i);
562  }
563 };
564 
565 
566 /*---------------------------------------------------------------------------*\
567  Class GeometricFieldConstRefWrap Declaration
568 \*---------------------------------------------------------------------------*/
569 
570 //- Expression wrap of const reference to GeometricField
571 template<class GeoField>
572 class GeometricFieldConstRefWrap
573 :
574  public GeometricFieldExpression
575  <
576  GeometricFieldConstRefWrap<GeoField>,
577  ListConstRefWrap<typename GeoField::value_type>,
578  ListConstRefWrap<typename GeoField::value_type>,
579  ListConstTmpWrap<Field<typename GeoField::value_type>>,
580  typename GeoField::value_type
581  >
582 {
583 public:
584 
585  static constexpr bool is_leaf = false; //true;
586 
587  //- True if GeoField is associated with a pointMesh
588  static constexpr bool is_pointField =
589  std::is_same_v<pointMesh, typename GeoField::Mesh>;
590 
591  //- The GeometricField type
592  typedef GeoField this_type;
593 
594  //- Type to return for internal field
595  typedef typename GeoField::value_type value_type;
596 
597  //- Type to return for patchField
601 
602 
603 private:
604 
605  const this_type& elems_;
606 
607 
608 public:
609 
610  // Construct from components
612  :
614  <
615  GeometricFieldConstRefWrap<GeoField>,
619  value_type
620  >
621  (
622  elems.dimensions(),
623  elems.oriented()
624  ),
625  elems_(elems)
626  {}
628  // return the underlying data
629  const auto& data() const
630  {
631  return elems_;
632  }
633 
634  value_type operator[](const label i) const
635  {
636  return elems_[i];
637  }
638 
639  auto size() const noexcept
640  {
641  return elems_.size();
642  }
643 
644  IntExpr internalField() const
645  {
646  return elems_.internalField();
647  }
648 
649  UncoupledPatchExpr patchField(const label i) const
650  {
651  //return elems_.boundaryField()[i];
652  const auto& fld = elems_.boundaryField()[i];
653 
654  if constexpr (is_pointField)
655  {
656  if (const auto* vp = isA<Field<value_type>>(fld))
657  {
658  return UncoupledPatchExpr(*vp);
659  }
660  else
661  {
663  }
664  }
665  else
666  {
668  }
669  }
670 
671  CoupledPatchExpr coupledPatchField(const label i) const
672  {
673  const auto& fld = elems_.boundaryField()[i];
674 
675  if constexpr (is_pointField)
676  {
677  if (const auto* vp = isA<Field<value_type>>(fld))
678  {
679  return CoupledPatchExpr(*vp);
680  }
681  else
682  {
683  return CoupledPatchExpr(tmp<Field<value_type>>(nullptr));
684  }
685  }
686  else
687  {
688  return CoupledPatchExpr(fld);
689  }
690  }
691 
692  template<class AccessOp>
693  auto access(const AccessOp& cop, const label i) const
694  {
695  return cop(elems_, i);
696  }
697 };
698 
700 /*---------------------------------------------------------------------------*\
701  Class GeometricFieldConstTmpWrap Declaration
702 \*---------------------------------------------------------------------------*/
703 
704 //- Expression wrap of const tmp to GeometricField
705 template<class GeoField>
707 :
709  <
710  GeometricFieldConstTmpWrap<GeoField>,
711  ListConstRefWrap<typename GeoField::value_type>,
712  ListConstRefWrap<typename GeoField::value_type>,
713  ListConstTmpWrap<Field<typename GeoField::value_type>>,
714  typename GeoField::value_type
715  >
716 {
717 public:
718 
719  //- Have expressions use copy to maintain tmp refCount
720  static constexpr bool is_leaf = false;
722  //- True if GeoField is associated with a pointMesh
723  static constexpr bool is_pointField =
724  std::is_same_v<pointMesh, typename GeoField::Mesh>;
725 
726  //- The GeometricField type
727  typedef GeoField this_type;
728 
729  //- Type to return for internal field
730  typedef typename GeoField::value_type value_type;
731 
732  //- Type to return for patchField
737 
738 private:
739 
740  const tmp<this_type> elems_;
741 
742 
743 public:
744 
745  // Construct from components
747  :
749  <
750  GeometricFieldConstTmpWrap<GeoField>,
751  IntExpr,
754  value_type
755  >
756  (
757  elems().dimensions(),
758  elems().oriented()
759  ),
760  elems_(elems, true)
761  {
762  //Pout<< "GeometricFieldConstTmpWrap :" << nl
763  // << " this_type : " << error::demangle<this_type>() << nl
764  // << " PatchExpr : " << error::demangle<IntExpr>() << nl
765  // << endl;
766  }
767 
769  (
771  )
772  :
774  <
776  IntExpr,
779  value_type
780  >
781  (
782  w.dimensions(),
783  w.oriented()
784  ),
785  elems_(w.elems_)
786  {
787  //Pout<< "GeometricFieldConstTmpWrap copy :" << nl
788  // << " this_type : " << error::demangle<this_type>() << nl
789  // << " PatchExpr : " << error::demangle<IntExpr>() << nl
790  // << endl;
791  }
792 
794  {
795  //Pout<< "~GeometricFieldConstTmpWrap destructor :" << nl
796  // << " this_type : " << error::demangle<this_type>() << nl
797  // << endl;
798  }
799 
800  // return the underlying data
801  const auto& data() const
802  {
803  return elems_();
804  }
805 
806  value_type operator[](const label i) const
807  {
808  // Redirection for every access. Slow?
809  return elems_()[i];
810  }
811 
812  auto size() const noexcept
813  {
814  return elems_().size();
815  }
816 
817  IntExpr internalField() const
818  {
819  return elems_().internalField();
820  }
821 
822  UncoupledPatchExpr patchField(const label i) const
823  {
824  const auto& fld = elems_().boundaryField()[i];
825 
826  if constexpr (is_pointField)
827  {
828  if (const auto* vp = isA<Field<value_type>>(fld))
829  {
830  return UncoupledPatchExpr(*vp);
831  }
832  else
833  {
835  }
836  }
837  else
838  {
839  return UncoupledPatchExpr(fld);
840  }
841  }
842 
843  CoupledPatchExpr coupledPatchField(const label i) const
844  {
845  const auto& fld = elems_().boundaryField()[i];
847  if constexpr (is_pointField)
848  {
849  if (const auto* vp = isA<Field<value_type>>(fld))
850  {
851  return CoupledPatchExpr(*vp);
852  }
853  else
854  {
856  }
857  }
858  else
859  {
860  return CoupledPatchExpr(fld);
861  }
862  }
863 
864  template<class AccessOp>
865  auto access(const AccessOp& cop, const label i) const
866  {
867  return cop(elems_(), i);
868  }
869 };
870 
871 
872 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
873 
874 // Expressions on GeometricFields
875 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
876 
877 // Do '+' ourselves - just to show. Others done with macros below.
878 template<typename E1, typename E2>
879 class GF_add
880 :
881  public GeometricFieldExpression
882  <
883  GF_add<E1, E2>,
884  List_add
885  <
886  typename E1::IntExpr,
887  typename E2::IntExpr
888  >,
889  List_add
890  <
891  typename E1::UncoupledPatchExpr,
892  typename E2::UncoupledPatchExpr
893  >,
894  List_add
895  <
896  typename E1::CoupledPatchExpr,
897  typename E2::CoupledPatchExpr
898  >,
899  typename E1::value_type
900  >
901 {
902  // cref if leaf, copy otherwise
906 public:
907  static constexpr bool is_leaf = false;
908 
909  //- Type to return for internal field
910  typedef typename E1::value_type value_type;
911 
912  //- Type to return for patchField
913  typedef List_add
914  <
915  typename E1::IntExpr,
916  typename E2::IntExpr
917  > IntExpr;
918  typedef List_add
919  <
920  typename E1::UncoupledPatchExpr,
921  typename E2::UncoupledPatchExpr
923  typedef List_add
924  <
925  typename E1::CoupledPatchExpr,
926  typename E2::CoupledPatchExpr
928 
929  GF_add(const E1& u, const E2& v)
930  :
932  <
933  GF_add<E1, E2>,
934  IntExpr,
937  value_type
938  >
939  (
940  u.dimensions() + v.dimensions(),
941  u.oriented() // + v.oriented()
942  ),
943  u_(u),
944  v_(v)
945  {
946  assert(u.size() == -1 || v.size() == -1 || u.size() == v.size());
947  static_assert
948  (
949  std::is_same_v
950  <
951  typename E1::value_type,
952  typename E2::value_type
953  > == true
954  );
955  }
956  auto operator[](const label i) const
957  {
958  return u_[i] + v_[i];
959  }
960  auto size() const noexcept { return Foam::max(u_.size(), v_.size()); }
962  IntExpr internalField() const
963  {
964  return IntExpr(u_.internalField(), v_.internalField());
965  }
967  UncoupledPatchExpr patchField(const label i) const
968  {
969  return UncoupledPatchExpr(u_.patchField(i), v_.patchField(i));
970  }
972  CoupledPatchExpr coupledPatchField(const label i) const
973  {
974  return CoupledPatchExpr
975  (
976  u_.coupledPatchField(i),
977  v_.coupledPatchField(i)
978  );
979  }
980 
981  template<class AccessOp>
982  auto access(const AccessOp& cop, const label i) const
983  {
984  return UncoupledPatchExpr(u_.access(cop, i), v_.access(cop, i));
985  }
986 };
987 template<typename E1, typename E2>
988 auto operator+
989 (
990  GeometricFieldExpression
991  <
992  E1,
993  typename E1::IntExpr,
994  typename E1::UncoupledPatchExpr,
995  typename E1::CoupledPatchExpr,
996  typename E1::value_type
997  > const& u,
998  GeometricFieldExpression
999  <
1000  E2,
1001  typename E2::IntExpr,
1002  typename E2::UncoupledPatchExpr,
1003  typename E2::CoupledPatchExpr,
1004  typename E2::value_type
1005  > const& v
1007 {
1008  return GF_add<E1, E2>
1009  (
1010  static_cast<const E1&>(u),
1011  static_cast<const E2&>(v)
1012  );
1013 }
1014 template<typename E1,class Type,template<class> class PatchField,class GeoMesh>
1015 auto operator+
1018  <
1019  E1,
1020  typename E1::IntExpr,
1021  typename E1::UncoupledPatchExpr,
1022  typename E1::CoupledPatchExpr,
1023  typename E1::value_type
1024  > const& u,
1027 {
1029  <
1031  > E2;
1032 
1033  return GF_add(static_cast<const E1&>(u), E2(v));
1034 }
1035 template<typename E1,class Type,template<class> class PatchField,class GeoMesh>
1036 auto operator+
1037 (
1039  GeometricFieldExpression
1040  <
1041  E1,
1042  typename E1::IntExpr,
1043  typename E1::UncoupledPatchExpr,
1044  typename E1::CoupledPatchExpr,
1045  typename E1::value_type
1046  > const& v
1047 )
1048 {
1050  <
1052  > E2;
1053  return GF_add(E2(u), static_cast<const E1&>(v));
1054 }
1055 template
1056 <class Type1, class Type2, template<class> class PatchField, class GeoMesh>
1057 auto operator+
1058 (
1059  GeometricField<Type1, PatchField, GeoMesh> const& u,
1061 )
1062 {
1064  <
1066  > E1;
1068  <
1070  > E2;
1071  return GF_add(E1(u), E2(v));
1072 }
1073 template<class Type, template<class> class PatchField, class GeoMesh>
1074 auto operator+
1075 (
1077  const dimensioned<Type>& v
1078 )
1079 {
1080  typedef typename Foam::GeometricField<Type, PatchField, GeoMesh> GeoField;
1083  return GF_add(E1(u), E2(u, v));
1084 }
1085 template<class Type, template<class> class PatchField, class GeoMesh>
1086 auto operator+
1087 (
1088  const dimensioned<Type>& u,
1090 )
1091 {
1092  typedef typename Foam::GeometricField<Type, PatchField, GeoMesh> GeoField;
1095  return GF_add(E2(v, u), E1(v));
1096 }
1097 
1098 // Negation
1099 template<typename E1>
1100 class GF_negate
1101 :
1103  <
1104  GF_negate<E1>,
1105  List_negate
1106  <
1107  typename E1::IntExpr
1108  >,
1109  List_negate
1110  <
1111  typename E1::UncoupledPatchExpr
1112  >,
1113  List_negate
1114  <
1115  typename E1::CoupledPatchExpr
1116  >,
1117  typename E1::value_type
1118  >
1120  // cref if leaf, copy otherwise
1122 
1123 public:
1124  static constexpr bool is_leaf = false;
1125 
1126  //- Type to return for internal field
1127  typedef typename E1::value_type value_type;
1128 
1129  //- Type to return for patchField
1133 
1134  GF_negate(const E1& u)
1135  :
1137  <
1138  GF_negate<E1>,
1139  IntExpr,
1142  value_type
1143  >
1144  (
1145  u.dimensions(),
1146  u.oriented()
1147  ),
1148  u_(u)
1149  {}
1150  auto operator[](const label i) const
1151  {
1152  return -u_[i];
1153  }
1154  auto size() const noexcept { return u_.size(); }
1155 
1156  IntExpr internalField() const
1157  {
1158  return u_.internalField();
1159  }
1160 
1161  UncoupledPatchExpr patchField(const label i) const
1162  {
1163  return u_.patchField(i);
1164  }
1165 
1166  CoupledPatchExpr coupledPatchField(const label i) const
1167  {
1168  return u_.coupledPatchField(i);
1169  }
1170 
1171  template<class AccessOp>
1172  auto access(const AccessOp& cop, const label i) const
1173  {
1174  return -u_.access(cop, i);
1175  }
1176 };
1177 template<typename E1>
1178 auto operator-
1181  <
1182  E1,
1183  typename E1::IntExpr,
1184  typename E1::UncoupledPatchExpr,
1185  typename E1::CoupledPatchExpr,
1186  typename E1::value_type
1187  > const& u
1188 )
1189 {
1190  return GF_negate<E1>(static_cast<const E1&>(u));
1191 }
1192 
1193 
1194 #undef EXPRESSION_GF_FUNCTION1_DIMLESS
1195 #define EXPRESSION_GF_FUNCTION1_DIMLESS(Func, BaseFunc, WrapType, OpFunc) \
1196 template<typename E1> \
1197 class OpFunc \
1198 : \
1199  public GeometricFieldExpression \
1200  < \
1201  OpFunc<E1>, \
1202  WrapType<typename E1::IntExpr>, \
1203  WrapType<typename E1::UncoupledPatchExpr>, \
1204  WrapType<typename E1::CoupledPatchExpr>, \
1205  typename E1::value_type \
1206  > \
1207 { \
1208  /* cref if leaf, copy otherwise */ \
1209  typename std::conditional<E1::is_leaf, const E1&, const E1>::type u_; \
1210  \
1211 public: \
1212  static constexpr bool is_leaf = false; \
1213  \
1214  /* Type to return for internal field */ \
1215  typedef typename E1::value_type value_type; \
1216  \
1217  /* Type to return for patchField */ \
1218  typedef WrapType<typename E1::IntExpr> IntExpr; \
1219  typedef WrapType<typename E1::UncoupledPatchExpr> UncoupledPatchExpr; \
1220  typedef WrapType<typename E1::CoupledPatchExpr> CoupledPatchExpr; \
1221  \
1222  OpFunc(const E1& u) \
1223  : \
1224  GeometricFieldExpression \
1225  < \
1226  OpFunc<E1>, \
1227  IntExpr, \
1228  UncoupledPatchExpr, \
1229  CoupledPatchExpr, \
1230  value_type \
1231  > \
1232  ( \
1233  u.dimensions(), \
1234  u.oriented() \
1235  ), \
1236  u_(u) \
1237  {} \
1238  auto operator[](const label i) const \
1239  { \
1240  return BaseFunc(u_[i]); \
1241  } \
1242  auto size() const noexcept { return u_.size(); } \
1243  \
1244  IntExpr internalField() const \
1245  { \
1246  return IntExpr(u_.internalField()); \
1247  } \
1248  \
1249  UncoupledPatchExpr patchField(const label i) const \
1250  { \
1251  return UncoupledPatchExpr(u_.patchField(i)); \
1252  } \
1253  \
1254  CoupledPatchExpr coupledPatchField(const label i) const \
1255  { \
1256  return CoupledPatchExpr(u_.coupledPatchField(i)); \
1257  } \
1258  \
1259  template<class AccessOpOp> \
1260  auto access(const AccessOpOp& cop, const label i) const \
1261  { \
1262  return UncoupledPatchExpr(u_.access(cop, i)); \
1263  } \
1264 }; \
1265 template<typename E1> \
1266 auto Func \
1267 ( \
1268  GeometricFieldExpression \
1269  < \
1270  E1, \
1271  typename E1::IntExpr, \
1272  typename E1::UncoupledPatchExpr, \
1273  typename E1::CoupledPatchExpr, \
1274  typename E1::value_type \
1275  > const& u \
1276 ) \
1277 { \
1278  return OpFunc<E1>(static_cast<const E1&>(u)); \
1279 } \
1280 template<class Type, template<class> class PatchField, class GeoMesh> \
1281 auto Func(GeometricField<Type, PatchField, GeoMesh> const& fld) \
1282 { \
1283  typedef typename Expression::GeometricFieldConstRefWrap \
1284  <GeometricField<Type, PatchField, GeoMesh>> E1; \
1285  return Func(E1(fld)); \
1286 }
1287 
1288 #undef EXPRESSION_GF_FUNCTION1
1289 #define EXPRESSION_GF_FUNCTION1(Func, BaseFunc, WrapType, OpFunc) \
1290 template<typename E1> \
1291 class OpFunc \
1292 : \
1293  public GeometricFieldExpression \
1294  < \
1295  OpFunc<E1>, \
1296  WrapType<typename E1::IntExpr>, \
1297  WrapType<typename E1::UncoupledPatchExpr>, \
1298  WrapType<typename E1::CoupledPatchExpr>, \
1299  typename E1::value_type \
1300  > \
1301 { \
1302  /* cref if leaf, copy otherwise */ \
1303  typename std::conditional<E1::is_leaf, const E1&, const E1>::type u_; \
1304  \
1305 public: \
1306  static constexpr bool is_leaf = false; \
1307  \
1308  /* Type to return for internal field */ \
1309  typedef typename E1::value_type value_type; \
1310  \
1311  /* Type to return for patchField */ \
1312  typedef WrapType<typename E1::IntExpr> IntExpr; \
1313  typedef WrapType<typename E1::UncoupledPatchExpr> UncoupledPatchExpr; \
1314  typedef WrapType<typename E1::CoupledPatchExpr> CoupledPatchExpr; \
1315  \
1316  OpFunc(const E1& u) \
1317  : \
1318  GeometricFieldExpression \
1319  < \
1320  OpFunc<E1>, \
1321  IntExpr, \
1322  UncoupledPatchExpr, \
1323  CoupledPatchExpr, \
1324  value_type \
1325  > \
1326  ( \
1327  BaseFunc(u.dimensions()), \
1328  BaseFunc(u.oriented()) \
1329  ), \
1330  u_(u) \
1331  {} \
1332  auto operator[](const label i) const \
1333  { \
1334  return BaseFunc(u_[i]); \
1335  } \
1336  auto size() const noexcept { return u_.size(); } \
1337  \
1338  IntExpr internalField() const \
1339  { \
1340  return IntExpr(u_.internalField()); \
1341  } \
1342  \
1343  UncoupledPatchExpr patchField(const label i) const \
1344  { \
1345  return UncoupledPatchExpr(u_.patchField(i)); \
1346  } \
1347  \
1348  CoupledPatchExpr coupledPatchField(const label i) const \
1349  { \
1350  return CoupledPatchExpr(u_.coupledPatchField(i)); \
1351  } \
1352  \
1353  template<class AccessOpOp> \
1354  auto access(const AccessOpOp& cop, const label i) const \
1355  { \
1356  return UncoupledPatchExpr(u_.access(cop, i)); \
1357  } \
1358 }; \
1359 template<typename E1> \
1360 auto Func \
1361 ( \
1362  GeometricFieldExpression \
1363  < \
1364  E1, \
1365  typename E1::IntExpr, \
1366  typename E1::UncoupledPatchExpr, \
1367  typename E1::CoupledPatchExpr, \
1368  typename E1::value_type \
1369  > const& u \
1370 ) \
1371 { \
1372  return OpFunc<E1>(static_cast<const E1&>(u)); \
1373 } \
1374 template<class Type, template<class> class PatchField, class GeoMesh> \
1375 auto Func(GeometricField<Type, PatchField, GeoMesh> const& fld) \
1376 { \
1377  typedef typename Expression::GeometricFieldConstRefWrap \
1378  <GeometricField<Type, PatchField, GeoMesh>> E1; \
1379  return Func(E1(fld)); \
1380 }
1381 
1382 
1384 //template<typename E1>
1385 //class GeometricFieldNegate
1386 //:
1387 // public GeometricFieldExpression
1388 // <
1389 // GeometricFieldNegate<E1>,
1390 // List_negate<typename E1::IntExpr>,
1391 // List_negate<typename E1::UncoupledPatchExpr>,
1392 // List_negate<typename E1::CoupledPatchExpr>,
1393 // typename E1::value_type
1394 // >
1395 //{
1396 // /* cref if leaf, copy otherwise */
1397 // typename std::conditional<E1::is_leaf, const E1&, const E1>::type u_;
1398 //
1399 //public:
1400 // static constexpr bool is_leaf = false;
1401 //
1402 // /* Type to return for internal field */
1403 // typedef typename E1::value_type value_type;
1404 //
1405 // /* Type to return for patchField */
1406 // typedef List_negate<typename E1::IntExpr> IntExpr;
1407 // typedef List_negate<typename E1::UncoupledPatchExpr> UncoupledPatchExpr;
1408 // typedef List_negate<typename E1::CoupledPatchExpr> CoupledPatchExpr;
1409 //
1410 // GeometricFieldNegate(const E1& u)
1411 // :
1412 // GeometricFieldExpression
1413 // <
1414 // GeometricFieldNegate<E1>,
1415 // IntExpr,
1416 // UncoupledPatchExpr,
1417 // CoupledPatchExpr,
1418 // value_type
1419 // >
1420 // (
1421 // -u.dimensions(),
1422 // -u.oriented()
1423 // ),
1424 // u_(u)
1425 // {}
1426 // auto operator[](const label i) const
1427 // {
1428 // return -u_[i];
1429 // }
1430 // label size() const { return u_.size(); }
1431 //
1432 // IntExpr internalField() const
1433 // {
1434 // return PatchExpr(u_.internalField());
1435 // }
1436 //
1437 // UncoupledPatchExpr patchField(const label i) const
1438 // {
1439 // return UncoupledPatchExpr(u_.patchField(i));
1440 // }
1441 //};
1442 //template<typename E1>
1443 //GeometricFieldNegate<E1> operator-
1444 //(
1445 // GeometricFieldExpression
1446 // <
1447 // E1,
1448 // typename E1::IntExpr,
1449 // typename E1::UncoupledPatchExpr,
1450 // typename E1::CoupledPatchExpr,
1451 // typename E1::value_type
1452 // > const& u
1453 //)
1454 //{
1455 // return GeometricFieldNegate<E1>(static_cast<const E1&>(u));
1456 //}
1457 
1458 #undef EXPRESSION_GF_OPERATOR
1459 #define EXPRESSION_GF_OPERATOR(Op, WrapType, OpFunc) \
1460 template<typename E1, typename E2> \
1461 class OpFunc \
1462 : \
1463  public GeometricFieldExpression \
1464  < \
1465  OpFunc<E1, E2>, \
1466  WrapType \
1467  < \
1468  typename E1::IntExpr, \
1469  typename E2::IntExpr \
1470  >, \
1471  WrapType \
1472  < \
1473  typename E1::UncoupledPatchExpr, \
1474  typename E2::UncoupledPatchExpr \
1475  >, \
1476  WrapType \
1477  < \
1478  typename E1::CoupledPatchExpr, \
1479  typename E2::CoupledPatchExpr \
1480  >, \
1481  typename E1::value_type \
1482  > \
1483 { \
1484  /* cref if leaf, copy otherwise */ \
1485  typename std::conditional<E1::is_leaf, const E1&, const E1>::type u_; \
1486  typename std::conditional<E2::is_leaf, const E2&, const E2>::type v_; \
1487  \
1488 public: \
1489  static constexpr bool is_leaf = false; \
1490  \
1491  /* Type to return for internal field */ \
1492  typedef typename E1::value_type value_type; \
1493  \
1494  /* Type to return for patchField */ \
1495  typedef WrapType \
1496  < \
1497  typename E1::IntExpr, \
1498  typename E2::IntExpr \
1499  > IntExpr; \
1500  typedef WrapType \
1501  < \
1502  typename E1::UncoupledPatchExpr, \
1503  typename E2::UncoupledPatchExpr \
1504  > UncoupledPatchExpr; \
1505  typedef WrapType \
1506  < \
1507  typename E1::CoupledPatchExpr, \
1508  typename E2::CoupledPatchExpr \
1509  > CoupledPatchExpr; \
1510  \
1511  OpFunc(const E1& u, const E2& v) \
1512  : \
1513  GeometricFieldExpression \
1514  < \
1515  OpFunc<E1, E2>, \
1516  IntExpr, \
1517  UncoupledPatchExpr, \
1518  CoupledPatchExpr, \
1519  typename E1::value_type \
1520  > \
1521  ( \
1522  u.dimensions() Op v.dimensions(), \
1523  u.oriented() Op v.oriented() \
1524  ), \
1525  u_(u), \
1526  v_(v) \
1527  { \
1528  /*static_assert \
1529  ( \
1530  std::is_same_v \
1531  < \
1532  typename E1::value_type, \
1533  typename E2::value_type \
1534  > == true \
1535  );*/ \
1536  assert(u.size() == -1 || v.size() == -1 || u.size() == v.size()); \
1537  } \
1538  auto operator[](const label i) const \
1539  { \
1540  return u_[i] Op v_[i]; \
1541  } \
1542  auto size() const noexcept { return Foam::max(u_.size(), v_.size()); } \
1543  \
1544  IntExpr internalField() const \
1545  { \
1546  return IntExpr(u_.internalField(), v_.internalField()); \
1547  } \
1548  \
1549  UncoupledPatchExpr patchField(const label i) const \
1550  { \
1551  return UncoupledPatchExpr(u_.patchField(i), v_.patchField(i)); \
1552  } \
1553  \
1554  CoupledPatchExpr coupledPatchField(const label i) const \
1555  { \
1556  return CoupledPatchExpr \
1557  ( \
1558  u_.coupledPatchField(i), \
1559  v_.coupledPatchField(i) \
1560  ); \
1561  } \
1562  \
1563  template<class AccessOp> \
1564  auto access(const AccessOp& cop, const label i) const \
1565  { \
1566  return UncoupledPatchExpr \
1567  ( \
1568  u_.access(cop, i), \
1569  v_.access(cop, i) \
1570  ); \
1571  } \
1572 }; \
1573 template<typename E1, typename E2> \
1574 auto operator Op \
1575 ( \
1576  GeometricFieldExpression \
1577  < \
1578  E1, \
1579  typename E1::IntExpr, \
1580  typename E1::UncoupledPatchExpr, \
1581  typename E1::CoupledPatchExpr, \
1582  typename E1::value_type \
1583  > const& u, \
1584  GeometricFieldExpression \
1585  < \
1586  E2, \
1587  typename E2::IntExpr, \
1588  typename E2::UncoupledPatchExpr, \
1589  typename E2::CoupledPatchExpr, \
1590  typename E2::value_type \
1591  > const& v \
1592 ) \
1593 { \
1594  return OpFunc<E1, E2> \
1595  ( \
1596  static_cast<const E1&>(u), \
1597  static_cast<const E2&>(v) \
1598  ); \
1599 } \
1600 template \
1601 < \
1602  typename E1, \
1603  class Type, template<class> class PatchField, class GeoMesh \
1604 > \
1605 auto operator Op \
1606 ( \
1607  GeometricFieldExpression \
1608  < \
1609  E1, \
1610  typename E1::IntExpr, \
1611  typename E1::UncoupledPatchExpr, \
1612  typename E1::CoupledPatchExpr, \
1613  typename E1::value_type \
1614  > const& u, \
1615  GeometricField<Type, PatchField, GeoMesh> const& fld \
1616 ) \
1617 { \
1618  typedef typename Expression::GeometricFieldConstRefWrap \
1619  <GeometricField<Type, PatchField, GeoMesh>> E2; \
1620  return operator Op(u, E2(fld)); \
1621 } \
1622 template \
1623 < \
1624  class Type, template<class> class PatchField, class GeoMesh, \
1625  typename E1 \
1626 > \
1627 auto operator Op \
1628 ( \
1629  GeometricField<Type, PatchField, GeoMesh> const& fld, \
1630  GeometricFieldExpression \
1631  < \
1632  E1, \
1633  typename E1::IntExpr, \
1634  typename E1::UncoupledPatchExpr, \
1635  typename E1::CoupledPatchExpr, \
1636  typename E1::value_type \
1637  > const& u \
1638 ) \
1639 { \
1640  typedef typename Expression::GeometricFieldConstRefWrap \
1641  <GeometricField<Type, PatchField, GeoMesh>> E2; \
1642  return operator Op(E2(fld), u); \
1643 } \
1644 template \
1645 <class Type1, class Type2, template<class> class PatchField, class GeoMesh> \
1646 auto operator Op \
1647 ( \
1648  GeometricField<Type1, PatchField, GeoMesh> const& u, \
1649  GeometricField<Type2, PatchField, GeoMesh> const& v \
1650 ) \
1651 { \
1652  typedef typename Expression::GeometricFieldConstRefWrap \
1653  <GeometricField<Type1, PatchField, GeoMesh>> E1; \
1654  typedef typename Expression::GeometricFieldConstRefWrap \
1655  <GeometricField<Type2, PatchField, GeoMesh>> E2; \
1656  return operator Op(E1(u), E2(v)); \
1657 } \
1658 /* Dimensioned types */ \
1659 template<typename E1, class Type> \
1660 auto operator Op \
1661 ( \
1662  GeometricFieldExpression \
1663  < \
1664  E1, \
1665  typename E1::IntExpr, \
1666  typename E1::UncoupledPatchExpr, \
1667  typename E1::CoupledPatchExpr, \
1668  typename E1::value_type \
1669  > const& u, \
1670  dimensioned<Type> const& v \
1671 ) \
1672 { \
1673  typedef typename Foam::Expression::UniformGeometricFieldWrap2<Type> E2; \
1674  return operator Op(u, E2(v)); \
1675 } \
1676 template<typename E1, class Type> \
1677 auto operator Op \
1678 ( \
1679  dimensioned<Type> const& u, \
1680  GeometricFieldExpression \
1681  < \
1682  E1, \
1683  typename E1::IntExpr, \
1684  typename E1::UncoupledPatchExpr, \
1685  typename E1::CoupledPatchExpr, \
1686  typename E1::value_type \
1687  > const& v \
1688 ) \
1689 { \
1690  typedef typename Foam::Expression::UniformGeometricFieldWrap2<Type> E2; \
1691  return operator Op(E2(u), v); \
1692 } \
1693 /* Primitive types */ \
1694 template \
1695 < \
1696  class Type1, class Type2, template<class> class PatchField, class GeoMesh, \
1697  class = std::enable_if_t \
1698  < \
1699  (std::is_arithmetic_v<Type2> || Foam::is_vectorspace_v<Type2>) \
1700  > \
1701 > \
1702 auto operator Op \
1703 ( \
1704  GeometricField<Type1, PatchField, GeoMesh> const& u, \
1705  Type2 const& v \
1706 ) \
1707 { \
1708  typedef typename Foam::GeometricField<Type1, PatchField, GeoMesh> GeoField;\
1709  typedef typename Expression::UniformGeometricFieldWrap<GeoField, Type2> E2;\
1710  return operator Op(u, E2(u, v)); \
1711 } \
1712 template \
1713 < \
1714  class Type1, class Type2, template<class> class PatchField, class GeoMesh, \
1715  class = std::enable_if_t \
1716  < \
1717  (std::is_arithmetic_v<Type2> || Foam::is_vectorspace_v<Type2>) \
1718  > \
1719 > \
1720 auto operator Op \
1721 ( \
1722  Type2 const& u, \
1723  GeometricField<Type1, PatchField, GeoMesh> const& v \
1724 ) \
1725 { \
1726  typedef typename Foam::GeometricField<Type1, PatchField, GeoMesh> GeoField;\
1727  typedef typename Expression::UniformGeometricFieldWrap<GeoField, Type2> E2;\
1728  return operator Op(E2(v, u), v); \
1729 } \
1730 /* GeoFields and Dimensioned types */ \
1731 template \
1732 < \
1733  class Type1, class Type2, template<class> class PatchField, class GeoMesh \
1734 > \
1735 auto operator Op \
1736 ( \
1737  GeometricField<Type1, PatchField, GeoMesh> const& u, \
1738  dimensioned<Type2> const& v \
1739 ) \
1740 { \
1741  typedef typename Foam::Expression::UniformGeometricFieldWrap \
1742  <GeometricField<Type1, PatchField, GeoMesh>, Type2> E2; \
1743  return operator Op(u, E2(u, v)); \
1744 } \
1745 template \
1746 < \
1747  class Type1, class Type2, template<class> class PatchField, class GeoMesh \
1748 > \
1749 auto operator Op \
1750 ( \
1751  dimensioned<Type2> const& u, \
1752  GeometricField<Type1, PatchField, GeoMesh> const& v \
1753 ) \
1754 { \
1755  typedef typename Foam::Expression::UniformGeometricFieldWrap \
1756  <GeometricField<Type1, PatchField, GeoMesh>, Type2> E2; \
1757  return operator Op(E2(v, u), v); \
1758 } \
1759 /* Expressions and primitive types */ \
1760 template \
1761 < \
1762  class E1, class Type2, \
1763  class = std::enable_if_t \
1764  < \
1765  (std::is_arithmetic_v<Type2> || Foam::is_vectorspace_v<Type2>) \
1766  > \
1767 > \
1768 auto operator Op \
1769 ( \
1770  GeometricFieldExpression \
1771  < \
1772  E1, \
1773  typename E1::IntExpr, \
1774  typename E1::UncoupledPatchExpr, \
1775  typename E1::CoupledPatchExpr, \
1776  typename E1::value_type \
1777  > const& u, \
1778  Type2 const& v \
1779 ) \
1780 { \
1781  typedef typename Foam::Expression::UniformGeometricFieldWrap2<Type2> E2; \
1782  return operator Op(u, E2(v)); \
1783 } \
1784 template \
1785 < \
1786  class E1, class Type2, \
1787  class = std::enable_if_t \
1788  < \
1789  (std::is_arithmetic_v<Type2> || Foam::is_vectorspace_v<Type2>) \
1790  > \
1791 > \
1792 auto operator Op \
1793 ( \
1794  Type2 const& u, \
1795  GeometricFieldExpression \
1796  < \
1797  E1, \
1798  typename E1::IntExpr, \
1799  typename E1::UncoupledPatchExpr, \
1800  typename E1::CoupledPatchExpr, \
1801  typename E1::value_type \
1802  > const& v \
1803 ) \
1804 { \
1805  typedef typename Foam::Expression::UniformGeometricFieldWrap2<Type2> E2; \
1806  return operator Op(E2(u), v); \
1807 } \
1808 
1809 
1810 #undef EXPRESSION_GF_FUNCTION2
1811 #define EXPRESSION_GF_FUNCTION2(Func, BaseFunc, WrapType, OpFunc) \
1812 template<typename E1, typename E2> \
1813 class OpFunc \
1814 : \
1815  public GeometricFieldExpression \
1816  < \
1817  OpFunc<E1, E2>, \
1818  WrapType \
1819  < \
1820  typename E1::IntExpr, \
1821  typename E2::IntExpr \
1822  >, \
1823  WrapType \
1824  < \
1825  typename E1::UncoupledPatchExpr, \
1826  typename E2::UncoupledPatchExpr \
1827  >, \
1828  WrapType \
1829  < \
1830  typename E1::CoupledPatchExpr, \
1831  typename E2::CoupledPatchExpr \
1832  >, \
1833  typename E1::value_type \
1834  > \
1835 { \
1836  /* cref if leaf, copy otherwise */ \
1837  typename std::conditional<E1::is_leaf, const E1&, const E1>::type u_; \
1838  typename std::conditional<E2::is_leaf, const E2&, const E2>::type v_; \
1839  \
1840 public: \
1841  static constexpr bool is_leaf = false; \
1842  \
1843  /* Type to return for internal field */ \
1844  typedef typename E1::value_type value_type; \
1845  \
1846  /* Type to return for patchField */ \
1847  typedef WrapType \
1848  < \
1849  typename E1::IntExpr, \
1850  typename E2::IntExpr \
1851  > IntExpr; \
1852  typedef WrapType \
1853  < \
1854  typename E1::UncoupledPatchExpr, \
1855  typename E2::UncoupledPatchExpr \
1856  > UncoupledPatchExpr; \
1857  typedef WrapType \
1858  < \
1859  typename E1::CoupledPatchExpr, \
1860  typename E2::CoupledPatchExpr \
1861  > CoupledPatchExpr; \
1862  \
1863  OpFunc(const E1& u, const E2& v) \
1864  : \
1865  GeometricFieldExpression \
1866  < \
1867  OpFunc<E1, E2>, \
1868  IntExpr, \
1869  UncoupledPatchExpr, \
1870  CoupledPatchExpr, \
1871  value_type \
1872  > \
1873  ( \
1874  BaseFunc(u.dimensions(), v.dimensions()), \
1875  BaseFunc(u.oriented(), v.oriented()) \
1876  ), \
1877  u_(u), \
1878  v_(v) \
1879  { \
1880  /*static_assert \
1881  ( \
1882  std::is_same_v \
1883  < \
1884  typename E1::value_type, \
1885  typename E2::value_type \
1886  > == true \
1887  );*/ \
1888  } \
1889  auto operator[](const label i) const \
1890  { \
1891  return BaseFunc(u_[i], v_[i]); \
1892  } \
1893  auto size() const noexcept {return Foam::max(u_.size(), v_.size()); } \
1894  \
1895  IntExpr internalField() const \
1896  { \
1897  return IntExpr(u_.internalField(), v_.internalField()); \
1898  } \
1899  \
1900  UncoupledPatchExpr patchField(const label i) const \
1901  { \
1902  return UncoupledPatchExpr(u_.patchField(i), v_.patchField(i)); \
1903  } \
1904  \
1905  CoupledPatchExpr coupledPatchField(const label i) const \
1906  { \
1907  return CoupledPatchExpr \
1908  ( \
1909  u_.coupledPatchField(i), \
1910  v_.coupledPatchField(i) \
1911  ); \
1912  } \
1913  \
1914  template<class AccessOp> \
1915  auto access(const AccessOp& cop, const label i) const \
1916  { \
1917  return UncoupledPatchExpr \
1918  ( \
1919  u_.access(cop, i), \
1920  v_.access(cop, i) \
1921  ); \
1922  } \
1923 }; \
1924 template<typename E1, typename E2> \
1925 auto Func \
1926 ( \
1927  GeometricFieldExpression \
1928  < \
1929  E1, \
1930  typename E1::IntExpr, \
1931  typename E1::UncoupledPatchExpr, \
1932  typename E1::CoupledPatchExpr, \
1933  typename E1::value_type \
1934  > const& u, \
1935  GeometricFieldExpression \
1936  < \
1937  E2, \
1938  typename E2::IntExpr, \
1939  typename E2::UncoupledPatchExpr, \
1940  typename E2::CoupledPatchExpr, \
1941  typename E2::value_type \
1942  > const& v \
1943 ) \
1944 { \
1945  return OpFunc<E1, E2> \
1946  ( \
1947  static_cast<const E1&>(u), \
1948  static_cast<const E2&>(v) \
1949  ); \
1950 } \
1951 template \
1952 < \
1953  typename E1, \
1954  class Type, template<class> class PatchField, class GeoMesh \
1955 > \
1956 auto Func \
1957 ( \
1958  GeometricFieldExpression \
1959  < \
1960  E1, \
1961  typename E1::IntExpr, \
1962  typename E1::UncoupledPatchExpr, \
1963  typename E1::CoupledPatchExpr, \
1964  typename E1::value_type \
1965  > const& u, \
1966  GeometricField<Type, PatchField, GeoMesh> const& fld \
1967 ) \
1968 { \
1969  typedef typename Expression::GeometricFieldConstRefWrap \
1970  <GeometricField<Type, PatchField, GeoMesh>> E2; \
1971  return Func(u, E2(fld)); \
1972 } \
1973 template \
1974 < \
1975  class Type, template<class> class PatchField, class GeoMesh, \
1976  typename E1 \
1977 > \
1978 auto Func \
1979 ( \
1980  GeometricField<Type, PatchField, GeoMesh> const& fld, \
1981  GeometricFieldExpression \
1982  < \
1983  E1, \
1984  typename E1::IntExpr, \
1985  typename E1::UncoupledPatchExpr, \
1986  typename E1::CoupledPatchExpr, \
1987  typename E1::value_type \
1988  > const& u \
1989 ) \
1990 { \
1991  typedef typename Expression::GeometricFieldConstRefWrap \
1992  <GeometricField<Type, PatchField, GeoMesh>> E2; \
1993  return Func(E2(fld), u); \
1994 } \
1995 template \
1996 < \
1997  class Type, template<class> class PatchField, class GeoMesh \
1998 > \
1999 auto Func \
2000 ( \
2001  GeometricField<Type, PatchField, GeoMesh> const& u, \
2002  GeometricField<Type, PatchField, GeoMesh> const& v \
2003 ) \
2004 { \
2005  typedef typename Expression::GeometricFieldConstRefWrap \
2006  <GeometricField<Type, PatchField, GeoMesh>> E2; \
2007  return Func(E2(u), E2(v)); \
2008 } \
2009 /* dimensioned types and geometric fields */ \
2010 template \
2011 < \
2012  class Type1, class Type2, template<class> class PatchField, class GeoMesh \
2013 > \
2014 auto Func \
2015 ( \
2016  GeometricField<Type1, PatchField, GeoMesh> const& u, \
2017  dimensioned<Type2> const& v \
2018 ) \
2019 { \
2020  typedef typename Foam::Expression::UniformGeometricFieldWrap \
2021  <GeometricField<Type1, PatchField, GeoMesh>, Type2> E2; \
2022  return Func(u, E2(u,v)); \
2023 } \
2024 template \
2025 < \
2026  class Type1, class Type2, template<class> class PatchField, class GeoMesh \
2027 > \
2028 auto Func \
2029 ( \
2030  dimensioned<Type2> const& u, \
2031  GeometricField<Type1, PatchField, GeoMesh> const& v \
2032 ) \
2033 { \
2034  typedef typename Foam::Expression::UniformGeometricFieldWrap \
2035  <GeometricField<Type1, PatchField, GeoMesh>, Type2> E2; \
2036  return Func(E2(v, u), v); \
2037 } \
2038 template<typename E1, class Type> \
2039 auto Func \
2040 ( \
2041  GeometricFieldExpression \
2042  < \
2043  E1, \
2044  typename E1::IntExpr, \
2045  typename E1::UncoupledPatchExpr, \
2046  typename E1::CoupledPatchExpr, \
2047  typename E1::value_type \
2048  > const& u, \
2049  dimensioned<Type> const& v \
2050 ) \
2051 { \
2052  typedef typename Foam::Expression::UniformGeometricFieldWrap2<Type> E2; \
2053  return Func(u, E2(v)); \
2054 } \
2055 template<typename E1, class Type> \
2056 auto Func \
2057 ( \
2058  dimensioned<Type> const& u, \
2059  GeometricFieldExpression \
2060  < \
2061  E1, \
2062  typename E1::IntExpr, \
2063  typename E1::UncoupledPatchExpr, \
2064  typename E1::CoupledPatchExpr, \
2065  typename E1::value_type \
2066  > const& v \
2067 ) \
2068 { \
2069  typedef typename Foam::Expression::UniformGeometricFieldWrap2<Type> E2; \
2070  return Func(E2(u), v); \
2071 } \
2072 
2073 
2074 //- GeometricField expressions.
2075 
2076 // macro arguments:
2077 // - 'sin' : name of new function (in Expression namespace)
2078 // - '::sin' : per-element function to call
2079 // - 'List_sin' : helper class to handle patchFields
2080 // - 'GF_sin' : generated expression helper class
2081 EXPRESSION_GF_FUNCTION1_DIMLESS(sin, ::sin, List_sin, GF_sin)
2082 EXPRESSION_GF_FUNCTION1_DIMLESS(cos, ::cos, List_cos, GF_cos)
2083 EXPRESSION_GF_FUNCTION1_DIMLESS(tan, ::tan, List_tan, GF_tan)
2084 EXPRESSION_GF_FUNCTION1_DIMLESS(sinh, ::sinh, List_sinh, GF_sinh)
2085 EXPRESSION_GF_FUNCTION1_DIMLESS(cosh, ::cosh, List_cosh, GF_cosh)
2086 EXPRESSION_GF_FUNCTION1_DIMLESS(tanh, ::tanh, List_tanh, GF_tanh)
2087 
2088 #undef EXPRESSION_GF_FUNCTION1_DIMLESS
2089 
2090 EXPRESSION_GF_FUNCTION1(sqr, Foam::sqr, List_sqr, GF_sqr)
2091 EXPRESSION_GF_FUNCTION1(sqrt, Foam::sqrt, List_sqrt, GF_sqrt)
2092 EXPRESSION_GF_FUNCTION1(magSqr, Foam::magSqr, List_magSqr, GF_magSqr)
2093 
2094 EXPRESSION_GF_FUNCTION1(mag, Foam::mag, List_mag, GF_mag)
2095 EXPRESSION_GF_FUNCTION1(symm, Foam::symm, List_symm, GF_symm)
2096 EXPRESSION_GF_FUNCTION1(pow2, Foam::pow2, List_pow2, GF_pow2)
2097 EXPRESSION_GF_FUNCTION1(pow3, Foam::pow3, List_pow3, GF_pow3)
2098 EXPRESSION_GF_FUNCTION1(pow4, Foam::pow4, List_pow4, GF_pow4)
2099 
2100 #undef EXPRESSION_GF_FUNCTION1
2101 
2102 EXPRESSION_GF_FUNCTION2(min, Foam::min, List_min, GF_min)
2103 EXPRESSION_GF_FUNCTION2(max, Foam::max, List_max, GF_max)
2104 
2105 #undef EXPRESSION_GF_FUNCTION2
2106 
2107 EXPRESSION_GF_OPERATOR(-, List_subtract, GF_subtract)
2108 EXPRESSION_GF_OPERATOR(*, List_multiply, GF_multiply)
2109 EXPRESSION_GF_OPERATOR(/, List_divide, GF_divide)
2110 EXPRESSION_GF_OPERATOR(&, List_dot, GF_dot)
2111 
2112 #undef EXPRESSION_GF_OPERATOR
2113 
2114 
2115 
2116 // Expressions on constants
2117 // ~~~~~~~~~~~~~~~~~~~~~~~~
2118 
2119 template<class GeoField, class Type = typename GeoField::value_type>
2120 class UniformGeometricFieldWrap
2121 :
2122  public GeometricFieldExpression
2123  <
2124  UniformGeometricFieldWrap<GeoField, Type>,
2125  UniformListWrap<Type>,
2126  UniformListWrap<Type>,
2127  UniformListWrap<Type>,
2128  Type
2129  >
2130 {
2131 public:
2133  static constexpr bool is_leaf = false; //true;
2135  //- Type to return for internal field
2136  typedef Type value_type;
2137 
2138  //- Type to return for patchField
2143 
2144 private:
2146  const GeoField& elems_;
2148  const value_type val_;
2149 
2150 public:
2151 
2152  // Construct from field (sizes only) and value
2153  UniformGeometricFieldWrap(const GeoField& elems, const value_type val)
2154  :
2156  <
2157  UniformGeometricFieldWrap<GeoField, Type>,
2161  value_type
2162  >
2163  (
2164  dimless,
2165  orientedType()
2166  ),
2167  elems_(elems),
2168  val_(val)
2169  {}
2170 
2171  // Construct from field (sizes only) and value, dimension
2173  (
2174  const GeoField& elems,
2175  const dimensioned<value_type>& val
2176  )
2177  :
2179  <
2180  UniformGeometricFieldWrap<GeoField, Type>,
2181  IntExpr,
2184  value_type
2185  >
2186  (
2187  val.dimensions(),
2189  ),
2190  elems_(elems),
2191  val_(val.value())
2192  {}
2194  value_type operator[](const label i) const
2195  {
2196  return val_;
2197  }
2198 
2199  auto size() const noexcept
2200  {
2201  return elems_.size();
2202  }
2203 
2204  IntExpr internalField() const
2205  {
2206  return IntExpr(elems_.internalField().size(), val_);
2207  }
2208 
2209  UncoupledPatchExpr patchField(const label i) const
2210  {
2211  return UncoupledPatchExpr(elems_.boundaryField()[i].size(), val_);
2212  }
2213 
2214  CoupledPatchExpr coupledPatchField(const label i) const
2215  {
2216  return CoupledPatchExpr(elems_.boundaryField()[i].size(), val_);
2217  }
2218 
2219  template<class AccessOp>
2220  auto access(const AccessOp& cop, const label i) const
2221  {
2222  // Size+value only
2223  return patchField(i);
2224  }
2225 };
2226 
2227 // Uniform value. Relies on size -1 being handled properly upstream.
2228 template<class T>
2230 :
2232  <
2233  UniformGeometricFieldWrap2<T>,
2234  UniformListWrap<T>,
2235  UniformListWrap<T>,
2236  UniformListWrap<T>,
2237  T
2238  >
2239 {
2240 public:
2241 
2242  static constexpr bool is_leaf = false; //true;
2243 
2244  //- The value type the list contains
2245  typedef T value_type;
2246 
2247  //- Type to return for patchField
2251 
2252 
2253 private:
2254 
2255  const T val_;
2256 
2257 
2258 public:
2259 
2260  // Construct from (dimensionless) value
2261  UniformGeometricFieldWrap2(const T val)
2262  :
2264  <
2266  IntExpr,
2269  T
2270  >
2271  (
2272  dimless,
2273  orientedType()
2274  ),
2275  val_(val)
2276  {}
2277 
2278  // Construct from value, dimension
2280  (
2281  const dimensioned<T>& val
2282  )
2283  :
2285  <
2287  IntExpr,
2290  T
2291  >
2292  (
2293  val.dimensions(),
2294  orientedType()
2295  ),
2296  val_(val.value())
2297  {}
2298 
2299  T operator[](const label i) const
2300  {
2301  return val_;
2302  }
2303 
2304  auto size() const noexcept
2305  {
2306  // Force error if used. Requires lower levels to use max() and hope
2307  // that one of the arguments has size.
2308  return -1;
2309  }
2310 
2311  IntExpr internalField() const
2312  {
2313  return IntExpr(-1, val_);
2314  }
2315 
2316  UncoupledPatchExpr patchField(const label i) const
2317  {
2318  return UncoupledPatchExpr(-1, val_);
2319  }
2320 
2321  CoupledPatchExpr coupledPatchField(const label i) const
2322  {
2323  return CoupledPatchExpr(-1, val_);
2324  }
2325 
2326  template<class AccessOp>
2327  auto access(const AccessOp& cop, const label i) const
2328  {
2329  // Size+value only
2330  return patchField(i);
2331  }
2332 };
2333 
2334 //- Fully self-contained constant field wrapper. Not needed?
2335 //template<class GeoField>
2336 //class UniformGeometricFieldWrap2
2337 //:
2338 // public GeometricFieldExpression
2339 // <
2340 // UniformGeometricFieldWrap2<GeoField>,
2341 // UniformListWrap<typename GeoField::value_type>,
2342 // typename GeoField::value_type
2343 // >
2344 //{
2345 //public:
2346 //
2347 // static constexpr bool is_leaf = true;
2348 //
2349 // //- Type to return for internal field
2350 // typedef typename GeoField::value_type value_type;
2351 //
2352 // //- Type to return for patchField
2353 // typedef UniformListWrap<value_type> PatchExpr;
2354 //
2355 //
2356 //private:
2357 //
2358 // const value_type val_;
2359 //
2360 // const label nInternal_;
2361 //
2362 // labelList patchSizes_;
2363 //
2364 // //const dimensionSet& dimensions_;
2365 //
2366 //public:
2367 //
2368 // // Construct from field (sizes only) and value
2369 // UniformGeometricFieldWrap2(const GeoField& elems, const value_type val)
2370 // :
2371 // val_(val),
2372 // nInternal_(elems.size()),
2373 // patchSizes_(elems.boundaryField().size())
2374 // //dimensions_(elems.dimensions()),
2375 // {
2376 // for (const auto& pfld : elems.boundaryField())
2377 // {
2378 // patchSizes_[pfld.patch().index()] = pfld.size();
2379 // }
2380 // }
2381 //
2382 // // Construct from field (sizes only) and value, dimension
2383 // UniformGeometricFieldWrap2
2384 // (
2385 // const GeoField& elems,
2386 // const dimensioned<value_type> val
2387 // )
2388 // :
2389 // val_(val.value()),
2390 // nInternal_(elems.size()),
2391 // patchSizes_(elems.boundaryField().size())
2392 // //dimensions_(val.dimensions()),
2393 // {
2394 // for (const auto& pfld : elems.boundaryField())
2395 // {
2396 // patchSizes_[pfld.patch().index()] = pfld.size();
2397 // }
2398 // }
2399 //
2400 // value_type operator[](const label i) const
2401 // {
2402 // return val_;
2403 // }
2404 //
2405 // auto size() const noexcept
2406 // {
2407 // return nInternal_;
2408 // }
2409 //
2410 // PatchExpr internalField() const
2411 // {
2412 // return PatchExpr(nInternal_, val_);
2413 // }
2414 //
2415 // PatchExpr patchField(const label i) const
2416 // {
2417 // return PatchExpr(patchSizes_[i], val_);
2418 // }
2419 //};
2420 
2421 
2422 /*
2423 // Some fvm functions using expressions
2424 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2425 
2426 // Supply a multiplier, either 1 or -1
2427 template<class Expr, class Expr2>
2428 void Su
2429 (
2430  fvMatrix<typename Expr::value_type>& m,
2431  const Expr2& mult,
2432  const Expr& expression
2433 )
2434 {
2435  //- Wrap of List as an expression
2436  typedef ListConstRefWrap<typename Expr::value_type> expr;
2437  //- Evaluator of an expression
2438  typedef ListRefWrap<typename Expr::value_type> evaluator;
2439 
2440  // Wrap mesh volume
2441  const expr V(m.psi().mesh().V());
2442 
2443  // Add expression to source
2444  auto& s = m.source();
2445  evaluator(s, expr(s) + mult*V*expression);
2446 }
2447 
2448 
2449 // Always add
2450 template<class Expr>
2451 void Su
2452 (
2453  fvMatrix<typename Expr::value_type>& m,
2454  const Expr& expression
2455 )
2456 {
2457  //- Wrap of List as an expression
2458  typedef ListConstRefWrap<typename Expr::value_type> expr;
2459  //- Evaluator of an expression
2460  typedef ListRefWrap<typename Expr::value_type> evaluator;
2461 
2462  // Wrap mesh volume
2463  const expr V(m.psi().mesh().V());
2464 
2465  // Add expression to source
2466  auto& s = m.source();
2467  evaluator(s, expr(s) + V*expression);
2468 }
2469 
2470 
2471 template<class Expr>
2472 void rhs
2473 (
2474  fvMatrix<typename Expr::value_type>& m,
2475  const Expr& expression
2476 )
2477 {
2478  Su(m, expression);
2479 }
2480 
2481 
2482 template<class Expr, class Expr2>
2483 void Sp
2484 (
2485  fvMatrix<typename Expr::value_type>& m,
2486  const Expr2& mult,
2487  const Expr& expression
2488 )
2489 {
2490  //- Wrap of List as an expression
2491  typedef ListConstRefWrap<typename Expr::value_type> expr;
2492  //- Evaluator of an expression
2493  typedef ListRefWrap<typename Expr::value_type> evaluator;
2494 
2495  // Wrap mesh volume
2496  const expr V(m.psi().mesh().V());
2497 
2498  // Add expression onto diag
2499  auto& d = m.diag();
2500  evaluator(d, expr(d) - mult*V*expression);
2501 }
2502 
2504 template<class Expr, class Expr2>
2505 void SuSp
2506 (
2507  fvMatrix<typename Expr::value_type>& m,
2508  const Expr2& mult,
2509  const Expr& expression
2510 )
2511 {
2512  //- Wrap of constant as a list expression
2513  typedef UniformListWrap<scalar> constant;
2514  //- Wrap of List as an expression
2515  typedef ListConstRefWrap<typename Expr::value_type> expr;
2516  //- Evaluator of an expression
2517  typedef ListRefWrap<typename Expr::value_type> evaluator;
2518 
2519  const constant constantZero(expression.size(), 0.0);
2520 
2521  // Wrap mesh volume
2522  const expr V(m.psi().mesh().V());
2523 
2524  // Linearise expression
2525  auto& diag = m.diag();
2526  auto& source = m.source();
2527 
2528  // diag() += domain*max(susp.field(), scalar(0));
2529  evaluator
2530  (
2531  diag,
2532  expr(diag) - mult*V*max(expression, constantZero)
2533  );
2534  // source() -= domain*min(susp.field(), scalar(0))*fld.primitiveField();
2535  evaluator
2536  (
2537  source,
2538  expr(source)
2539  + (
2540  mult
2541  *V
2542  *min(expression, constantZero)
2543  *expr(m.psi().internalField())
2544  )
2545  );
2546 }
2547 */
2548 
2549 
2550 } // End namespace Expression
2551 
2552 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
2554 } // End namespace Foam
2555 
2556 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
2557 
2558 #endif
2559 
2560 // ************************************************************************* //
const orientedType & oriented() const noexcept
Expression wrap of multiple lists.
auto access(const AccessOp &cop, const label i) const
static constexpr bool is_pointField
True if GeoField is associated with a pointMesh.
type
Types of root.
Definition: Roots.H:52
E1::value_type value_type
Type to return for internal field.
this_type & evaluate(const GeometricFieldExpression< E, typename E::IntExpr, typename E::UncoupledPatchExpr, typename E::CoupledPatchExpr, typename E::value_type > &expr)
Evaluate and return as GeoField. Rename to evaluate to make it clear it takes time? Or leave as indexing for convenience?
UniformGeometricFieldWrap(const GeoField &elems, const value_type val)
Expression wrap of const reference to UList.
Definition: UList.H:81
GeoField::value_type value_type
Type to return for internal field.
CoupledPatchExpr coupledPatchField(const label i)
auto cosh(GeometricFieldExpression< E1, typename E1::IntExpr, typename E1::UncoupledPatchExpr, typename E1::CoupledPatchExpr, typename E1::value_type > const &u)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
static constexpr bool is_leaf
Have expressions use copy to maintain tmp refCount.
auto max(GeometricFieldExpression< E1, typename E1::IntExpr, typename E1::UncoupledPatchExpr, typename E1::CoupledPatchExpr, typename E1::value_type > const &u, GeometricFieldExpression< E2, typename E2::IntExpr, typename E2::UncoupledPatchExpr, typename E2::CoupledPatchExpr, typename E2::value_type > const &v)
GeometricFieldRefWrap(this_type &elems)
Copy construct.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Expression wrap of const tmp to List.
List_add< typename E1::UncoupledPatchExpr, typename E2::UncoupledPatchExpr > UncoupledPatchExpr
T value_type
The value type the list contains.
dimensionedScalar sqrt(const dimensionedScalar &ds)
GeoField & evaluate(GeoField &fld, const bool force=false) const
Helper to evaluate a GeometricField.
#define Op(opName, op)
Definition: ops.H:99
List_add< typename E1::CoupledPatchExpr, typename E2::CoupledPatchExpr > CoupledPatchExpr
List_add< typename E1::IntExpr, typename E2::IntExpr > IntExpr
Type to return for patchField.
Generic GeometricField class.
Class to determine the &#39;oriented&#39; status of surface fields.
Definition: orientedType.H:52
Generic dimensioned Type class.
ListConstTmpWrap< Field< value_type > > CoupledPatchExpr
const dimensionSet dimless
Dimensionless.
CoupledPatchExpr coupledPatchField(const label i) const
UncoupledPatchExpr patchField(const label i) const
CoupledPatchExpr coupledPatchField(const label i) const
auto operator[](const label i) const
UniformListWrap< value_type > IntExpr
Type to return for patchField.
Expression wrap of const tmp to GeometricField.
UncoupledPatchExpr patchField(const label i)
#define EXPRESSION_GF_FUNCTION1(Func, BaseFunc, WrapType, OpFunc)
UncoupledPatchExpr patchField(const label i) const
Expression wrap of const reference to GeometricField.
Type * isA_constCast(const U &obj)
Attempt dynamic_cast to Type followed by a const_cast of the result.
Definition: typeInfo.H:101
auto mag(GeometricFieldExpression< E1, typename E1::IntExpr, typename E1::UncoupledPatchExpr, typename E1::CoupledPatchExpr, typename E1::value_type > const &u)
Dimension set for the base types, which can be used to implement rigorous dimension checking for alge...
Definition: dimensionSet.H:105
CoupledPatchExpr coupledPatchField(const label i)
List_negate< typename E1::CoupledPatchExpr > CoupledPatchExpr
auto operator[](const label i) const
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition: Field.H:69
const dimensionSet & dimensions() const noexcept
ListConstRefWrap< typename Expr::value_type > expr
Fully self-contained constant field wrapper. Not needed?
List_negate< typename E1::UncoupledPatchExpr > UncoupledPatchExpr
auto access(const AccessOp &cop, const label i) const
GeoField::value_type value_type
Type to return for internal field.
ListRefWrap< value_type > IntExpr
Type to return for patchField.
CoupledPatchExpr coupledPatchField(const label i) const
#define EXPRESSION_GF_FUNCTION1_DIMLESS(Func, BaseFunc, WrapType, OpFunc)
g_symm< E1 > symm(const GenericExpression< E1 > &u)
auto access(const Op &cop, const label i) const
g_sqr< E1 > sqr(const GenericExpression< E1 > &u)
Expression wrap of tmp to List.
Expression wrap of non-const reference to GeometricField.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
dimensionSet pow2(const dimensionSet &ds)
Definition: dimensionSet.C:352
E1::value_type value_type
Type to return for internal field.
auto tanh(GeometricFieldExpression< E1, typename E1::IntExpr, typename E1::UncoupledPatchExpr, typename E1::CoupledPatchExpr, typename E1::value_type > const &u)
const direction noexcept
Definition: scalarImpl.H:265
auto access(const AccessOp &cop, const label i) const
g_pow3< E1 > pow3(const GenericExpression< E1 > &u)
auto min(GeometricFieldExpression< E1, typename E1::IntExpr, typename E1::UncoupledPatchExpr, typename E1::CoupledPatchExpr, typename E1::value_type > const &u, GeometricFieldExpression< E2, typename E2::IntExpr, typename E2::UncoupledPatchExpr, typename E2::CoupledPatchExpr, typename E2::value_type > const &v)
#define EXPRESSION_GF_FUNCTION2(Func, BaseFunc, WrapType, OpFunc)
UncoupledPatchExpr patchField(const label i) const
g_pow4< E1 > pow4(const GenericExpression< E1 > &u)
auto access(const AccessOp &cop, const label i) const
GF_add(const E1 &u, const E2 &v)
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
dimensionedScalar pow3(const dimensionedScalar &ds)
auto sin(GeometricFieldExpression< E1, typename E1::IntExpr, typename E1::UncoupledPatchExpr, typename E1::CoupledPatchExpr, typename E1::value_type > const &u)
CoupledPatchExpr coupledPatchField(const label i) const
auto access(const AccessOp &cop, const label i) const
GeoField::value_type value_type
Type to return for internal field.
Container & evaluate(Container &lst) const
Helper: assign to passed in list.
static constexpr bool is_pointField
True if GeoField is associated with a pointMesh.
dimensionedSymmTensor symm(const dimensionedSymmTensor &dt)
auto access(const AccessOp &cop, const label i) const
ListConstRefWrap< value_type > IntExpr
Type to return for patchField.
auto access(const AccessOp &cop, const label i) const
value_type operator[](const label i) const
UncoupledPatchExpr patchField(const label i) const
dimensionedScalar pow4(const dimensionedScalar &ds)
g_magSqr< E1 > magSqr(const GenericExpression< E1 > &u)
Expression wrap of non-const reference to List.
GeoField this_type
The GeometricField type.
auto cos(GeometricFieldExpression< E1, typename E1::IntExpr, typename E1::UncoupledPatchExpr, typename E1::CoupledPatchExpr, typename E1::value_type > const &u)
label n
auto tan(GeometricFieldExpression< E1, typename E1::IntExpr, typename E1::UncoupledPatchExpr, typename E1::CoupledPatchExpr, typename E1::value_type > const &u)
static constexpr bool is_pointField
True if GeoField is associated with a pointMesh.
auto sinh(GeometricFieldExpression< E1, typename E1::IntExpr, typename E1::UncoupledPatchExpr, typename E1::CoupledPatchExpr, typename E1::value_type > const &u)
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition: typeInfo.H:87
GeometricFieldConstTmpWrap(const tmp< this_type > &elems)
g_pow2< E1 > pow2(const GenericExpression< E1 > &u)
Generic mesh wrapper used by volMesh, surfaceMesh, pointMesh etc.
Definition: GeoMesh.H:45
UncoupledPatchExpr patchField(const label i)
#define EXPRESSION_GF_OPERATOR(Op, WrapType, OpFunc)
UniformListWrap< T > IntExpr
Type to return for patchField.
A class for managing temporary objects.
Definition: HashPtrTable.H:50
GeometricFieldExpression(const dimensionSet &dimensions, const orientedType oriented)
Expression templates for List.
ListTmpWrap< Field< value_type > > CoupledPatchExpr
ListConstTmpWrap< Field< value_type > > CoupledPatchExpr
UncoupledPatchExpr patchField(const label i) const
void evaluate(ListsRefWrap< E > &exprWarp, const Container &ds)
Assignment of selected elements.
static const List< T > & null() noexcept
Return a null List (reference to a nullObject). Behaves like an empty List.
Definition: List.H:137
CoupledPatchExpr coupledPatchField(const label i) const
CoupledPatchExpr coupledPatchField(const label i) const
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
UncoupledPatchExpr patchField(const label i) const
g_sqrt< E1 > sqrt(const GenericExpression< E1 > &u)
Namespace for OpenFOAM.
Type value_type
Type to return for internal field.
List_negate< typename E1::IntExpr > IntExpr
Type to return for patchField.
ListConstRefWrap< value_type > IntExpr
Type to return for patchField.
Expression wrap of a List with a uniform value.