GeometricField.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2025 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "GeometricField.H"
30 #include "Time.H"
31 #include "dictionary.H"
33 #include "meshState.H"
34 
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 
37 // Check that both fields use the same mesh
38 #undef checkField
39 #define checkField(fld1, fld2, op) \
40 if (&(fld1).mesh() != &(fld2).mesh()) \
41 { \
42  FatalErrorInFunction \
43  << "Different mesh for fields " \
44  << (fld1).name() << " and " << (fld2).name() \
45  << " during operation " << op \
46  << abort(FatalError); \
47 }
48 
49 
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
51 
52 template<class Type, template<class> class PatchField, class GeoMesh>
54 (
55  const dictionary& dict
56 )
57 {
58  Internal::readField(dict, "internalField"); // Includes size check
59 
60  boundaryField_.readField(*this, dict.subDict("boundaryField"));
61 
62  Type refLevel;
63 
64  if (dict.readIfPresent("referenceLevel", refLevel))
65  {
66  // Add to internal (primitive) field
67  this->field() += refLevel;
68 
69  // Add to boundary fields
70  forAll(boundaryField_, patchi)
71  {
72  boundaryField_[patchi] == boundaryField_[patchi] + refLevel;
73  }
74  }
75 }
76 
77 
78 template<class Type, template<class> class PatchField, class GeoMesh>
80 {
82  (
83  localIOdictionary::readContents
84  (
85  IOobject
86  (
87  this->name(),
88  this->instance(),
89  this->local(),
90  this->db(),
91  IOobjectOption::MUST_READ,
92  IOobjectOption::NO_WRITE,
93  IOobjectOption::NO_REGISTER
94  ),
95  typeName
96  )
97  );
98 
99  this->close();
100 
101  readFields(dict);
102 }
103 
104 
105 template<class Type, template<class> class PatchField, class GeoMesh>
107 {
108  if (this->isReadRequired())
109  {
111  << "The readOption MUST_READ or READ_MODIFIED"
112  << " suggests that a read constructor for field " << this->name()
113  << " would be more appropriate." << endl;
114  }
115  else if
116  (
117  this->isReadOptional()
118  && this->template typeHeaderOk<this_type>(true) // checkType = true
119  )
120  {
121  readFields();
122  readOldTimeIfPresent();
123 
124  return true;
125  }
126 
127  return false;
128 }
129 
130 
131 template<class Type, template<class> class PatchField, class GeoMesh>
133 {
134  // Read the old time field if present
135  IOobject field0
136  (
137  this->name() + "_0",
138  this->time().timeName(),
139  this->db(),
140  IOobjectOption::LAZY_READ,
141  IOobjectOption::AUTO_WRITE,
142  this->registerObject()
143  );
144 
145  if
146  (
147  field0.template typeHeaderOk<this_type>(true) // checkType = true
148  )
149  {
151  << "Reading old time level for field" << nl << this->info() << endl;
152 
153  field0Ptr_ = std::make_unique<this_type>(field0, this->mesh());
154 
155  // Ensure the old time field oriented flag is set to the parent's state
156  // Note: required for backwards compatibility in case of restarting from
157  // an old run where the oriented state may not have been set
158  field0Ptr_->oriented() = this->oriented();
159 
160  field0Ptr_->timeIndex_ = timeIndex_ - 1;
161 
162  if (!field0Ptr_->readOldTimeIfPresent())
163  {
164  field0Ptr_->oldTime();
165  }
166 
167  return true;
168  }
169 
170  return false;
171 }
172 
173 
174 // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
175 
176 template<class Type, template<class> class PatchField, class GeoMesh>
178 (
179  const IOobject& io,
180  const Mesh& mesh,
181  const dimensionSet& dims,
182  const word& patchFieldType
183 )
184 :
185  Internal(io, mesh, dims, false),
186  timeIndex_(this->time().timeIndex()),
187  boundaryField_(mesh.boundary(), *this, patchFieldType)
188 {
190  << "Creating" << nl << this->info() << endl;
192  readIfPresent();
193 }
194 
195 
196 template<class Type, template<class> class PatchField, class GeoMesh>
198 (
199  const IOobject& io,
200  const Mesh& mesh,
201  const dimensionSet& dims,
202  const wordList& patchFieldTypes,
203  const wordList& actualPatchTypes
204 )
205 :
206  Internal(io, mesh, dims, false),
207  timeIndex_(this->time().timeIndex()),
208  boundaryField_(mesh.boundary(), *this, patchFieldTypes, actualPatchTypes)
209 {
211  << "Creating" << nl << this->info() << endl;
213  readIfPresent();
214 }
215 
216 
217 template<class Type, template<class> class PatchField, class GeoMesh>
219 (
220  const IOobject& io,
221  const Mesh& mesh,
222  const Type& value,
223  const dimensionSet& dims,
224  const word& patchFieldType
225 )
226 :
227  Internal(io, mesh, value, dims, false),
228  timeIndex_(this->time().timeIndex()),
229  boundaryField_(mesh.boundary(), *this, patchFieldType)
230 {
232  << "Creating" << nl << this->info() << endl;
233 
234  boundaryField_ == value;
236  readIfPresent();
237 }
238 
239 
240 template<class Type, template<class> class PatchField, class GeoMesh>
242 (
243  const IOobject& io,
244  const Mesh& mesh,
245  const Type& value,
246  const dimensionSet& dims,
247  const wordList& patchFieldTypes,
248  const wordList& actualPatchTypes
249 )
250 :
251  Internal(io, mesh, value, dims, false),
252  timeIndex_(this->time().timeIndex()),
253  boundaryField_(mesh.boundary(), *this, patchFieldTypes, actualPatchTypes)
254 {
256  << "Creating" << nl << this->info() << endl;
257 
258  boundaryField_ == value;
260  readIfPresent();
261 }
262 
263 
264 template<class Type, template<class> class PatchField, class GeoMesh>
266 (
267  const IOobject& io,
268  const Mesh& mesh,
269  const dimensioned<Type>& dt,
270  const word& patchFieldType
271 )
272 :
273  GeometricField<Type, PatchField, GeoMesh>
274  (
275  io,
276  mesh,
277  dt.value(),
278  dt.dimensions(),
279  patchFieldType
280  )
281 {}
282 
283 
284 template<class Type, template<class> class PatchField, class GeoMesh>
286 (
287  const IOobject& io,
288  const Mesh& mesh,
289  const dimensioned<Type>& dt,
290  const wordList& patchFieldTypes,
291  const wordList& actualPatchTypes
292 )
293 :
294  GeometricField<Type, PatchField, GeoMesh>
295  (
296  io,
297  mesh,
298  dt.value(),
299  dt.dimensions(),
300  patchFieldTypes,
301  actualPatchTypes
302  )
303 {}
304 
305 
306 template<class Type, template<class> class PatchField, class GeoMesh>
308 (
309  const IOobject& io,
310  const Internal& diField,
311  const PtrList<PatchField<Type>>& ptfl
312 )
313 :
314  Internal(io, diField),
315  timeIndex_(this->time().timeIndex()),
316  boundaryField_(this->mesh().boundary(), *this, ptfl)
317 {
319  << "Copy construct from components" << nl << this->info() << endl;
321  readIfPresent();
322 }
323 
324 
325 template<class Type, template<class> class PatchField, class GeoMesh>
327 (
328  const IOobject& io,
329  Internal&& diField,
330  const PtrList<PatchField<Type>>& ptfl
331 )
332 :
333  Internal(io, std::move(diField)),
334  timeIndex_(this->time().timeIndex()),
335  boundaryField_(this->mesh().boundary(), *this, ptfl)
336 {
338  << "Move construct from components" << nl << this->info() << endl;
340  readIfPresent();
341 }
342 
343 
344 template<class Type, template<class> class PatchField, class GeoMesh>
346 (
347  const IOobject& io,
348  const tmp<Internal>& tfield,
349  const PtrList<PatchField<Type>>& ptfl
350 )
351 :
352  Internal(io, tfield),
353  timeIndex_(this->time().timeIndex()),
354  boundaryField_(this->mesh().boundary(), *this, ptfl)
355 {
357  << "Construct from tmp internalField" << nl << this->info() << endl;
359  readIfPresent();
360 }
361 
362 
363 template<class Type, template<class> class PatchField, class GeoMesh>
365 (
366  const Internal& diField,
367  const PtrList<PatchField<Type>>& ptfl
368 )
369 :
370  Internal(diField),
371  timeIndex_(this->time().timeIndex()),
372  boundaryField_(this->mesh().boundary(), *this, ptfl)
373 {
375  << "Copy construct from components" << nl << this->info() << endl;
377  readIfPresent();
378 }
379 
380 
381 template<class Type, template<class> class PatchField, class GeoMesh>
383 (
384  Internal&& diField,
385  const PtrList<PatchField<Type>>& ptfl
386 )
387 :
388  Internal(std::move(diField)),
389  timeIndex_(this->time().timeIndex()),
390  boundaryField_(this->mesh().boundary(), *this, ptfl)
391 {
393  << "Move construct from components" << nl << this->info() << endl;
395  readIfPresent();
396 }
397 
398 
399 template<class Type, template<class> class PatchField, class GeoMesh>
401 (
402  const IOobject& io,
403  const Mesh& mesh,
404  const dimensionSet& dims,
405  const Field<Type>& iField,
406  const word& patchFieldType
407 )
408 :
409  Internal(io, mesh, dims, iField),
410  timeIndex_(this->time().timeIndex()),
411  boundaryField_(mesh.boundary(), *this, patchFieldType)
412 {
414  << "Copy construct from primitive field" << nl << this->info() << endl;
416  readIfPresent();
417 }
418 
419 
420 template<class Type, template<class> class PatchField, class GeoMesh>
422 (
423  const IOobject& io,
424  const Mesh& mesh,
425  const dimensionSet& dims,
426  Field<Type>&& iField,
427  const word& patchFieldType
428 )
429 :
430  Internal(io, mesh, dims, std::move(iField)),
431  timeIndex_(this->time().timeIndex()),
432  boundaryField_(mesh.boundary(), *this, patchFieldType)
433 {
435  << "Move construct from primitive field" << nl << this->info() << endl;
437  readIfPresent();
438 }
439 
440 
441 template<class Type, template<class> class PatchField, class GeoMesh>
443 (
444  const IOobject& io,
445  const Mesh& mesh,
446  const dimensionSet& dims,
447  const tmp<Field<Type>>& tfield,
448  const word& patchFieldType
449 )
450 :
451  Internal(io, mesh, dims, tfield),
452  timeIndex_(this->time().timeIndex()),
453  boundaryField_(mesh.boundary(), *this, patchFieldType)
454 {
456  << "Construct from tmp primitive field" << nl << this->info() << endl;
458  readIfPresent();
459 }
460 
461 
462 template<class Type, template<class> class PatchField, class GeoMesh>
464 (
465  const IOobject& io,
466  const Mesh& mesh,
467  const dimensionSet& dims,
468  const Field<Type>& iField,
469  const PtrList<PatchField<Type>>& ptfl
470 )
471 :
472  Internal(io, mesh, dims, iField),
473  timeIndex_(this->time().timeIndex()),
474  boundaryField_(mesh.boundary(), *this, ptfl)
475 {
477  << "Copy construct from components" << nl << this->info() << endl;
479  readIfPresent();
480 }
481 
482 
483 template<class Type, template<class> class PatchField, class GeoMesh>
485 (
486  const IOobject& io,
487  const Mesh& mesh,
488  const dimensionSet& dims,
489  Field<Type>&& iField,
490  const PtrList<PatchField<Type>>& ptfl
491 )
492 :
493  Internal(io, mesh, dims, std::move(iField)),
494  timeIndex_(this->time().timeIndex()),
495  boundaryField_(mesh.boundary(), *this, ptfl)
496 {
498  << "Move construct from components" << nl << this->info() << endl;
500  readIfPresent();
501 }
502 
503 
504 template<class Type, template<class> class PatchField, class GeoMesh>
506 (
507  const IOobject& io,
508  const Mesh& mesh,
509  const dimensionSet& dims,
510  const tmp<Field<Type>>& tfield,
511  const PtrList<PatchField<Type>>& ptfl
512 )
513 :
514  Internal(io, mesh, dims, tfield),
515  timeIndex_(this->time().timeIndex()),
516  boundaryField_(mesh.boundary(), *this, ptfl)
517 {
519  << "Construct from tmp internalField" << nl << this->info() << endl;
521  readIfPresent();
522 }
523 
524 
525 template<class Type, template<class> class PatchField, class GeoMesh>
527 (
528  const IOobject& io,
529  const Mesh& mesh,
530  const bool readOldTime
531 )
532 :
533  Internal(io, mesh, dimless, false),
534  timeIndex_(this->time().timeIndex()),
535  boundaryField_(mesh.boundary())
536 {
538  << "Read construct" << nl << this->info() << endl;
539 
540  if (!this->isAnyRead())
541  {
542  // Do not warn about LAZY_READ since we may have already checked
543  // the IOobject before calling.
545  << "Had readOption NO_READ for field "
546  << this->name() << ", but constructor always reads field!"
547  << endl;
548  }
549 
550  readFields();
551 
552  if (readOldTime)
553  {
554  readOldTimeIfPresent();
555  }
556 
558  << "Finishing read-construction" << nl << this->info() << endl;
559 }
560 
561 
562 template<class Type, template<class> class PatchField, class GeoMesh>
564 (
565  const IOobject& io,
566  const Mesh& mesh,
567  const dictionary& dict
568 )
569 :
570  Internal(io, mesh, dimless, false),
571  timeIndex_(this->time().timeIndex()),
572  boundaryField_(mesh.boundary())
573 {
574  readFields(dict);
575 
577  << "Finishing dictionary-construct" << nl << this->info() << endl;
578 }
579 
580 
581 template<class Type, template<class> class PatchField, class GeoMesh>
583 (
585 )
586 :
587  Internal(gf),
588  timeIndex_(gf.timeIndex()),
589  boundaryField_(*this, gf.boundaryField_)
590 {
592  << "Copy construct" << nl << this->info() << endl;
593 
594  if (gf.field0Ptr_)
595  {
596  field0Ptr_ = std::make_unique<this_type>(*gf.field0Ptr_);
597  }
599  this->writeOpt(IOobjectOption::NO_WRITE);
600 }
601 
602 
603 template<class Type, template<class> class PatchField, class GeoMesh>
605 (
607 )
608 :
609  Internal(tgf.constCast(), tgf.movable()),
610  timeIndex_(tgf().timeIndex()),
611  boundaryField_(*this, tgf().boundaryField_)
612 {
614  << "Constructing from tmp" << nl << this->info() << endl;
615 
616  this->writeOpt(IOobjectOption::NO_WRITE);
618  tgf.clear();
619 }
620 
621 
622 template<class Type, template<class> class PatchField, class GeoMesh>
624 (
625  const IOobject& io,
627 )
628 :
629  Internal(io, gf),
630  timeIndex_(gf.timeIndex()),
631  boundaryField_(*this, gf.boundaryField_)
632 {
634  << "Copy construct, resetting IO params" << nl
635  << this->info() << endl;
636 
637  if (!readIfPresent() && gf.field0Ptr_)
638  {
639  field0Ptr_ = std::make_unique<this_type>
640  (
641  io.name() + "_0",
642  *gf.field0Ptr_
643  );
644  }
645 }
646 
647 
648 template<class Type, template<class> class PatchField, class GeoMesh>
650 (
651  const IOobject& io,
652  const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
653 )
654 :
655  Internal(io, tgf.constCast(), tgf.movable()),
656  timeIndex_(tgf().timeIndex()),
657  boundaryField_(*this, tgf().boundaryField_)
658 {
660  << "Constructing from tmp resetting IO params" << nl
661  << this->info() << endl;
662 
663  tgf.clear();
665  readIfPresent();
666 }
667 
668 
669 template<class Type, template<class> class PatchField, class GeoMesh>
671 (
672  const word& newName,
674 )
675 :
676  Internal(newName, gf),
677  timeIndex_(gf.timeIndex()),
678  boundaryField_(*this, gf.boundaryField_)
679 {
681  << "Copy construct, resetting name" << nl
682  << this->info() << endl;
683 
684  if (!readIfPresent() && gf.field0Ptr_)
685  {
686  field0Ptr_ = std::make_unique<this_type>
687  (
688  newName + "_0",
689  *gf.field0Ptr_
690  );
691  }
692 }
693 
694 
695 template<class Type, template<class> class PatchField, class GeoMesh>
697 (
698  const word& newName,
699  const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
700 )
701 :
702  Internal(newName, tgf.constCast(), tgf.movable()),
703  timeIndex_(tgf().timeIndex()),
704  boundaryField_(*this, tgf().boundaryField_)
705 {
707  << "Constructing from tmp resetting name" << nl
708  << this->info() << endl;
710  tgf.clear();
711 }
712 
713 
714 template<class Type, template<class> class PatchField, class GeoMesh>
716 (
717  const IOobject& io,
719  const word& patchFieldType
720 )
721 :
722  Internal(io, gf),
723  timeIndex_(gf.timeIndex()),
724  boundaryField_(this->mesh().boundary(), *this, patchFieldType)
725 {
727  << "Copy construct, resetting IO params" << nl
728  << this->info() << endl;
729 
730  boundaryField_ == gf.boundaryField_;
731 
732  if (!readIfPresent() && gf.field0Ptr_)
733  {
734  field0Ptr_ = std::make_unique<this_type>
735  (
736  io.name() + "_0",
737  *gf.field0Ptr_
738  );
739  }
740 }
741 
742 
743 template<class Type, template<class> class PatchField, class GeoMesh>
745 (
746  const IOobject& io,
747  const GeometricField<Type, PatchField, GeoMesh>& gf,
748  const wordList& patchFieldTypes,
749  const wordList& actualPatchTypes
750 )
751 :
752  Internal(io, gf),
753  timeIndex_(gf.timeIndex()),
754  boundaryField_
755  (
756  this->mesh().boundary(),
757  *this,
758  patchFieldTypes,
759  actualPatchTypes
760  )
761 {
763  << "Copy construct, resetting IO params and patch types" << nl
764  << this->info() << endl;
765 
766  boundaryField_ == gf.boundaryField_;
767 
768  if (!readIfPresent() && gf.field0Ptr_)
769  {
770  field0Ptr_ = std::make_unique<this_type>
771  (
772  io.name() + "_0",
773  *gf.field0Ptr_
774  );
775  }
776 }
777 
778 
779 template<class Type, template<class> class PatchField, class GeoMesh>
781 (
782  const IOobject& io,
783  const GeometricField<Type, PatchField, GeoMesh>& gf,
784  const labelList& patchIDs,
785  const word& patchFieldType
786 )
787 :
788  Internal(io, gf),
789  timeIndex_(gf.timeIndex()),
790  boundaryField_(*this, gf.boundaryField_, patchIDs, patchFieldType)
791 {
793  << "Copy construct, resetting IO params and setting patchFieldType "
794  << "for patchIDs" << nl
795  << this->info() << endl;
796 
797  if (!readIfPresent() && gf.field0Ptr_)
798  {
799  field0Ptr_ = std::make_unique<this_type>
800  (
801  io.name() + "_0",
802  *gf.field0Ptr_
803  );
804  }
805 }
806 
807 
808 template<class Type, template<class> class PatchField, class GeoMesh>
810 (
811  const IOobject& io,
812  const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf,
813  const wordList& patchFieldTypes,
814  const wordList& actualPatchTypes
815 )
816 :
817  Internal(io, tgf.constCast(), tgf.movable()),
818  timeIndex_(tgf().timeIndex()),
819  boundaryField_
820  (
821  this->mesh().boundary(),
822  *this,
823  patchFieldTypes,
824  actualPatchTypes
825  )
826 {
828  << "Constructing from tmp resetting IO params and patch types" << nl
829  << this->info() << endl;
830 
831  boundaryField_ == tgf().boundaryField_;
833  tgf.clear();
834 }
835 
836 
837 template<class Type, template<class> class PatchField, class GeoMesh>
840 {
842 }
843 
844 
845 // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * * //
846 
847 template<class Type, template<class> class PatchField, class GeoMesh>
849 {
850  /*
851  if (debug)
852  {
853  // Problem: temporary fields might have their internal field
854  // already stolen so boundary fields will not be able to access the
855  // internal field anymore
856  boundaryField_.check();
857  }
858  */
859 
860  // FUTURE: register cache field info
861  // // this->db().cacheTemporaryObject(*this);
862 }
863 
865 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
866 
867 template<class Type, template<class> class PatchField, class GeoMesh>
868 typename
871 (
872  const bool updateAccessTime
873 )
874 {
875  if (updateAccessTime)
876  {
877  this->setUpToDate();
878  storeOldTimes();
879  }
880  return *this;
881 }
882 
883 
884 template<class Type, template<class> class PatchField, class GeoMesh>
885 typename
888 (
889  const bool updateAccessTime
890 )
891 {
892  if (updateAccessTime)
893  {
894  this->setUpToDate();
895  storeOldTimes();
896  }
897  return *this;
898 }
899 
900 
901 template<class Type, template<class> class PatchField, class GeoMesh>
902 typename
905 (
906  const bool updateAccessTime
907 )
908 {
909  if (updateAccessTime)
910  {
911  this->setUpToDate();
912  storeOldTimes();
913  }
914  return boundaryField_;
915 }
916 
917 
918 template<class Type, template<class> class PatchField, class GeoMesh>
919 Foam::label
921 {
922  return (field0Ptr_ ? (field0Ptr_->nOldTimes() + 1) : 0);
923 }
924 
925 
926 template<class Type, template<class> class PatchField, class GeoMesh>
928 {
929  if
930  (
931  field0Ptr_
932  && timeIndex_ != this->time().timeIndex()
933  && !this->name().ends_with("_0")
934  )
935  {
936  storeOldTime();
937  timeIndex_ = this->time().timeIndex();
938  }
940  // Correct time index
941  //timeIndex_ = this->time().timeIndex();
942 }
943 
944 
945 template<class Type, template<class> class PatchField, class GeoMesh>
947 {
948  if (field0Ptr_)
949  {
950  field0Ptr_->storeOldTime();
951 
953  << "Storing old time field for field" << nl << this->info() << endl;
954 
955  *field0Ptr_ == *this;
956  field0Ptr_->timeIndex_ = timeIndex_;
957 
958  if (field0Ptr_->field0Ptr_)
959  {
960  field0Ptr_->writeOpt(this->writeOpt());
961  }
962  }
963 }
964 
965 
966 template<class Type, template<class> class PatchField, class GeoMesh>
969 {
970  if (!field0Ptr_)
971  {
972  field0Ptr_ = std::make_unique<this_type>
973  (
974  IOobject
975  (
976  this->name() + "_0",
977  this->time().timeName(),
978  this->db(),
979  IOobjectOption::NO_READ,
980  IOobjectOption::NO_WRITE,
981  this->registerObject()
982  ),
983  *this
984  );
985 
986  if (debug)
987  {
989  << "created old time field " << field0Ptr_->info() << endl;
990 
991  if (debug&2)
992  {
993  error::printStack(Info);
994  }
995  }
996  }
997  else
998  {
999  storeOldTimes();
1000  }
1002  return *field0Ptr_;
1003 }
1004 
1005 
1006 template<class Type, template<class> class PatchField, class GeoMesh>
1009 {
1010  static_cast<const GeometricField<Type, PatchField, GeoMesh>&>(*this)
1012 
1013  return *field0Ptr_;
1014 }
1015 
1016 
1017 template<class Type, template<class> class PatchField, class GeoMesh>
1019 {
1020  if (!fieldPrevIterPtr_)
1021  {
1023  << "Allocating previous iteration field" << nl
1024  << this->info() << endl;
1025 
1026  fieldPrevIterPtr_ = std::make_unique<this_type>
1027  (
1028  this->name() + "PrevIter",
1029  *this
1030  );
1031  }
1032  else
1033  {
1034  *fieldPrevIterPtr_ == *this;
1035  }
1036 }
1037 
1038 
1039 template<class Type, template<class> class PatchField, class GeoMesh>
1042 {
1043  if (!fieldPrevIterPtr_)
1044  {
1046  << "previous iteration field" << endl << this->info() << endl
1047  << " not stored."
1048  << " Use field.storePrevIter() at start of iteration."
1049  << abort(FatalError);
1050  }
1051 
1052  return *fieldPrevIterPtr_;
1053 }
1054 
1055 
1056 template<class Type, template<class> class PatchField, class GeoMesh>
1058 {
1059  field0Ptr_.reset(nullptr);
1060  fieldPrevIterPtr_.reset(nullptr);
1061 }
1062 
1063 
1064 template<class Type, template<class> class PatchField, class GeoMesh>
1067 {
1068  // updateAccessTime
1069  {
1070  this->setUpToDate();
1071  storeOldTimes();
1072  }
1073  boundaryField_.evaluate();
1074 }
1075 
1076 
1077 template<class Type, template<class> class PatchField, class GeoMesh>
1080 {
1081  // updateAccessTime
1082  {
1083  this->setUpToDate();
1084  storeOldTimes();
1085  }
1086  boundaryField_.evaluateLocal();
1087 }
1088 
1089 
1090 template<class Type, template<class> class PatchField, class GeoMesh>
1092 {
1093  // Search all boundary conditions, if any are
1094  // fixed-value or mixed (Robin) do not set reference level for solution.
1095 
1096  bool needRef = true;
1097 
1098  for (const auto& pf : boundaryField_)
1099  {
1100  if (pf.fixesValue())
1101  {
1102  needRef = false;
1103  break;
1104  }
1105  }
1106 
1107  return returnReduceAnd(needRef);
1108 }
1109 
1110 
1111 template<class Type, template<class> class PatchField, class GeoMesh>
1113 {
1115  << "Relaxing" << nl << this->info() << " by " << alpha << endl;
1116 
1117  operator==(prevIter() + alpha*(*this - prevIter()));
1118 }
1119 
1120 
1121 template<class Type, template<class> class PatchField, class GeoMesh>
1123 {
1124  word name = this->name();
1125 
1126  if (this->mesh().data().isFinalIteration())
1127  {
1128  name += "Final";
1129  }
1130 
1131  scalar relaxCoeff = 1;
1132 
1133  if (this->mesh().relaxField(name, relaxCoeff))
1134  {
1135  relax(relaxCoeff);
1136  }
1137 }
1138 
1139 
1140 template<class Type, template<class> class PatchField, class GeoMesh>
1142 (
1143  bool final
1144 ) const
1145 {
1146  if (final)
1147  {
1148  return this->name() + "Final";
1149  }
1151  return this->name();
1152 }
1153 
1154 
1155 template<class Type, template<class> class PatchField, class GeoMesh>
1157 (
1158  Ostream& os,
1159  label comm
1160 ) const
1161 {
1162  MinMax<Type> range = Foam::minMax(*this, comm).value();
1163 
1164  os << "min/max(" << this->name() << ") = "
1165  << range.min() << ", " << range.max() << endl;
1166 }
1167 
1168 
1169 template<class Type, template<class> class PatchField, class GeoMesh>
1171 writeData(Ostream& os) const
1172 {
1173  this->internalField().writeData(os, "internalField");
1174  os << nl;
1175  this->boundaryField().writeEntry("boundaryField", os);
1176 
1177  os.check(FUNCTION_NAME);
1178  return os.good();
1180 
1181 
1182 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1183 
1184 template<class Type, template<class> class PatchField, class GeoMesh>
1187 {
1189  (
1190  this->name() + ".T()",
1191  this->mesh(),
1192  this->dimensions()
1193  );
1194 
1195  Foam::T(tresult.ref().primitiveFieldRef(), primitiveField());
1196  Foam::T(tresult.ref().boundaryFieldRef(), boundaryField());
1197 
1198  return tresult;
1199 }
1200 
1201 
1202 template<class Type, template<class> class PatchField, class GeoMesh>
1203 Foam::tmp
1204 <
1206  <
1208  PatchField,
1209  GeoMesh
1210  >
1211 >
1213 (
1214  const direction d
1215 ) const
1216 {
1218  (
1219  this->name() + ".component(" + Foam::name(d) + ')',
1220  this->mesh(),
1221  this->dimensions()
1222  );
1223 
1224  Foam::component(tresult.ref().primitiveFieldRef(), primitiveField(), d);
1225  Foam::component(tresult.ref().boundaryFieldRef(), boundaryField(), d);
1226 
1227  return tresult;
1228 }
1229 
1230 
1231 template<class Type, template<class> class PatchField, class GeoMesh>
1233 (
1234  const direction d,
1235  const GeometricField
1236  <
1237  typename GeometricField<Type, PatchField, GeoMesh>::cmptType,
1238  PatchField,
1239  GeoMesh
1240  >& gcf
1241 )
1242 {
1243  primitiveFieldRef().replace(d, gcf.primitiveField());
1244  boundaryFieldRef().replace(d, gcf.boundaryField());
1245 }
1246 
1247 
1248 template<class Type, template<class> class PatchField, class GeoMesh>
1250 (
1251  const direction d,
1252  const dimensioned<cmptType>& ds
1253 )
1254 {
1255  primitiveFieldRef().replace(d, ds.value());
1256  boundaryFieldRef().replace(d, ds.value());
1257 }
1258 
1259 
1260 template<class Type, template<class> class PatchField, class GeoMesh>
1262 (
1263  const Type& lower
1264 )
1265 {
1266  primitiveFieldRef().clamp_min(lower);
1267  boundaryFieldRef().clamp_min(lower);
1268 }
1269 
1270 
1271 template<class Type, template<class> class PatchField, class GeoMesh>
1273 (
1274  const Type& upper
1275 )
1276 {
1277  primitiveFieldRef().clamp_max(upper);
1278  boundaryFieldRef().clamp_max(upper);
1279 }
1280 
1281 
1282 template<class Type, template<class> class PatchField, class GeoMesh>
1284 (
1285  const dimensioned<Type>& lower
1286 )
1288  this->clamp_min(lower.value());
1289 }
1290 
1291 
1292 template<class Type, template<class> class PatchField, class GeoMesh>
1294 (
1295  const dimensioned<Type>& upper
1296 )
1298  this->clamp_max(upper.value());
1299 }
1300 
1301 
1302 template<class Type, template<class> class PatchField, class GeoMesh>
1304 (
1306 )
1307 {
1308  primitiveFieldRef().clamp_min(lower.primitiveField());
1309  boundaryFieldRef().clamp_min(lower.boundaryField());
1310  correctLocalBoundaryConditions();
1312  {
1313  boundaryField().check();
1314  }
1315 }
1316 
1317 
1318 template<class Type, template<class> class PatchField, class GeoMesh>
1320 (
1321  const GeometricField<Type, PatchField, GeoMesh>& upper
1322 )
1323 {
1324  primitiveFieldRef().clamp_max(upper.primitiveField());
1325  boundaryFieldRef().clamp_max(upper.boundaryField());
1326  correctLocalBoundaryConditions();
1328  {
1329  boundaryField().check();
1330  }
1331 }
1332 
1333 
1334 template<class Type, template<class> class PatchField, class GeoMesh>
1336 (
1337  const Type& lower,
1338  const Type& upper
1339 )
1340 {
1341  primitiveFieldRef().clamp_range(lower, upper);
1342  boundaryFieldRef().clamp_range(lower, upper);
1343 }
1344 
1345 
1346 template<class Type, template<class> class PatchField, class GeoMesh>
1348 (
1349  const MinMax<Type>& range
1350 )
1351 {
1352  primitiveFieldRef().clamp_range(range.min(), range.max());
1353  boundaryFieldRef().clamp_range(range.min(), range.max());
1354 }
1355 
1356 
1357 template<class Type, template<class> class PatchField, class GeoMesh>
1359 (
1360  const dimensioned<Type>& lower,
1361  const dimensioned<Type>& upper
1362 )
1364  this->clamp_range(lower.value(), upper.value());
1365 }
1366 
1367 
1368 template<class Type, template<class> class PatchField, class GeoMesh>
1370 (
1373 {
1374  this->clamp_range(range.value());
1375 }
1376 
1377 
1378 template<class Type, template<class> class PatchField, class GeoMesh>
1381  primitiveFieldRef().negate();
1382  boundaryFieldRef().negate();
1383 }
1384 
1385 
1386 template<class Type, template<class> class PatchField, class GeoMesh>
1388 {
1389  primitiveFieldRef().normalise();
1390  boundaryFieldRef().normalise();
1392 
1393 
1394 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1395 
1396 template<class Type, template<class> class PatchField, class GeoMesh>
1398 (
1400 )
1401 {
1402  if (this == &gf)
1403  {
1404  return; // Self-assignment is a no-op
1405  }
1406 
1407  checkField(*this, gf, "=");
1408 
1409  // Only assign field contents not ID
1410 
1411  internalFieldRef() = gf.internalField();
1413 
1414  // Make sure any e.g. jump-cyclic are updated.
1415  boundaryFieldRef().evaluate_if
1416  (
1417  [](const auto& pfld) { return pfld.constraintOverride(); }
1418  );
1419 }
1420 
1421 
1422 template<class Type, template<class> class PatchField, class GeoMesh>
1424 (
1425  const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
1426 )
1427 {
1428  const auto& gf = tgf();
1429 
1430  if (this == &gf)
1431  {
1432  return; // Self-assignment is a no-op
1433  }
1434 
1435  checkField(*this, gf, "=");
1436 
1437  // Only assign field contents not ID
1438 
1439  this->dimensions() = gf.dimensions();
1440  this->oriented() = gf.oriented();
1441 
1442  if (tgf.movable())
1443  {
1444  // Transfer storage from the tmp
1445  primitiveFieldRef().transfer(tgf.constCast().primitiveFieldRef());
1446  }
1447  else
1448  {
1450  }
1451 
1453 
1454  tgf.clear();
1455 
1456  // Make sure any e.g. jump-cyclic are updated.
1457  boundaryFieldRef().evaluate_if
1458  (
1459  [](const auto& pfld) { return pfld.constraintOverride(); }
1460  );
1461 }
1462 
1463 
1464 template<class Type, template<class> class PatchField, class GeoMesh>
1466 (
1467  const dimensioned<Type>& dt
1468 )
1469 {
1470  internalFieldRef() = dt;
1471  boundaryFieldRef() = dt.value();
1472 
1473  // Make sure any e.g. jump-cyclic are updated.
1474  boundaryFieldRef().evaluate_if
1475  (
1476  [](const auto& pfld) { return pfld.constraintOverride(); }
1477  );
1478 }
1479 
1480 
1481 template<class Type, template<class> class PatchField, class GeoMesh>
1483 (
1484  const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
1485 )
1486 {
1487  const auto& gf = tgf();
1488 
1489  checkField(*this, gf, "==");
1490 
1491  // Only assign field contents not ID
1492 
1493  internalFieldRef() = gf.internalField();
1494  boundaryFieldRef() == gf.boundaryField();
1495 
1496  tgf.clear();
1497 
1498  // Make sure any e.g. jump-cyclic are updated.
1499  boundaryFieldRef().evaluate_if
1500  (
1501  [](const auto& pfld) { return pfld.constraintOverride(); }
1502  );
1503 }
1504 
1505 
1506 template<class Type, template<class> class PatchField, class GeoMesh>
1508 (
1509  const dimensioned<Type>& dt
1510 )
1511 {
1512  internalFieldRef() = dt;
1513  boundaryFieldRef() == dt.value();
1514 
1515  // Make sure any e.g. jump-cyclic are updated.
1516  boundaryFieldRef().evaluate_if
1517  (
1518  [](const auto& pfld) { return pfld.constraintOverride(); }
1519  );
1520 }
1521 
1522 
1523 #define COMPUTED_ASSIGNMENT(TYPE, op) \
1524  \
1525 template<class Type, template<class> class PatchField, class GeoMesh> \
1526 void Foam::GeometricField<Type, PatchField, GeoMesh>::operator op \
1527 ( \
1528  const GeometricField<TYPE, PatchField, GeoMesh>& gf \
1529 ) \
1530 { \
1531  checkField(*this, gf, #op); \
1532  \
1533  internalFieldRef() op gf.internalField(); \
1534  boundaryFieldRef() op gf.boundaryField(); \
1535  \
1536  boundaryFieldRef().evaluate_if \
1537  ( \
1538  [](const auto& pfld) { return pfld.constraintOverride(); } \
1539  ); \
1540 } \
1541  \
1542 template<class Type, template<class> class PatchField, class GeoMesh> \
1543 void Foam::GeometricField<Type, PatchField, GeoMesh>::operator op \
1544 ( \
1545  const tmp<GeometricField<TYPE, PatchField, GeoMesh>>& tgf \
1546 ) \
1547 { \
1548  operator op(tgf()); \
1549  tgf.clear(); \
1550  \
1551  boundaryFieldRef().evaluate_if \
1552  ( \
1553  [](const auto& pfld) { return pfld.constraintOverride(); } \
1554  ); \
1555 } \
1556  \
1557 template<class Type, template<class> class PatchField, class GeoMesh> \
1558 void Foam::GeometricField<Type, PatchField, GeoMesh>::operator op \
1559 ( \
1560  const dimensioned<TYPE>& dt \
1561 ) \
1562 { \
1563  internalFieldRef() op dt; \
1564  boundaryFieldRef() op dt.value(); \
1565  \
1566  boundaryFieldRef().evaluate_if \
1567  ( \
1568  [](const auto& pfld) { return pfld.constraintOverride(); } \
1569  ); \
1570 }
1571 
1572 COMPUTED_ASSIGNMENT(Type, +=)
1573 COMPUTED_ASSIGNMENT(Type, -=)
1574 COMPUTED_ASSIGNMENT(scalar, *=)
1575 COMPUTED_ASSIGNMENT(scalar, /=)
1576 
1577 #undef COMPUTED_ASSIGNMENT
1578 
1579 
1580 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
1581 
1582 template<class Type, template<class> class PatchField, class GeoMesh>
1583 Foam::Ostream& Foam::operator<<
1584 (
1585  Ostream& os,
1587 )
1588 {
1589  fld.writeData(os);
1590  return os;
1591 }
1592 
1593 
1594 template<class Type, template<class> class PatchField, class GeoMesh>
1595 Foam::Ostream& Foam::operator<<
1596 (
1597  Ostream& os,
1599 )
1600 {
1601  tfld().writeData(os);
1602  tfld.clear();
1603 
1604  return os;
1605 }
1606 
1607 
1608 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1609 
1610 #undef checkField
1611 
1612 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1613 
1614 #include "GeometricFieldNew.C"
1615 #include "GeometricFieldFunctions.C"
1616 
1617 // ************************************************************************* //
void clamp_min(const Type &lower)
Impose lower (floor) clamp on the field values (in-place)
faceListList boundary
rho clamp_range(rhoMin[i], rhoMax[i])
const labelList patchIDs(pbm.indices(polyPatchNames, true))
void clamp_range(const dimensioned< MinMax< Type >> &range)
Clamp field values (in-place) to the specified range.
#define COMPUTED_ASSIGNMENT(TYPE, op)
const Type & value() const noexcept
Return const reference to value.
dictionary dict
const GeometricField< Type, PatchField, GeoMesh > & oldTime() const
Return old time field.
rDeltaTY field()
uint8_t direction
Definition: direction.H:46
const Internal::FieldType & primitiveField() const noexcept
Return a const-reference to the internal field values.
UEqn relax()
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
Y [inertIndex] clamp_min(0)
void clearOldTimes()
Remove old-time and prev-iter fields.
Field< Type >::cmptType cmptType
Component type of the field elements.
const Internal & internalField() const noexcept
Return a const-reference to the dimensioned internal field.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
A min/max value pair with additional methods. In addition to conveniently storing values...
Definition: HashSet.H:72
GeometricField(const IOobject &io, const Mesh &mesh, const dimensionSet &dims, const word &patchFieldType=PatchField< Type >::calculatedType())
Construct given IOobject, mesh, dimensions and patch type.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
tmp< GeometricField< cmptType, PatchField, GeoMesh > > component(const direction) const
Return a component of the field.
label nOldTimes() const noexcept
The number of old time fields stored.
void writeMinMax(Ostream &os, label comm=UPstream::worldComm) const
Helper function to write the min and max to an Ostream.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
const T & min() const noexcept
The min value.
Definition: MinMax.H:207
Generic GeometricField class.
Generic dimensioned Type class.
const dimensionSet dimless
Dimensionless.
bool writeData(Ostream &os) const
The writeData function (required by regIOobject)
word select(bool final) const
Select the final iteration parameters if final is true by returning the field name + "Final" otherwis...
conserve primitiveFieldRef()+
scalar range
orientedType oriented() const noexcept
Return oriented type.
MinMax< label > minMax(const labelHashSet &set)
Find the min/max values of labelHashSet.
Definition: hashSets.C:54
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
word timeName
Definition: getTimeIndex.H:3
bool needReference() const
Does the field need a reference level for solution.
Dimension set for the base types, which can be used to implement rigorous dimension checking for alge...
Definition: dimensionSet.H:105
dynamicFvMesh & mesh
void storeOldTimes() const
Store the old-time fields.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
Generic templated field type.
Definition: Field.H:63
void readFields(const typename GeoFieldType::Mesh &mesh, const IOobjectList &objects, const NameMatchPredicate &selectedFields, DynamicList< regIOobject *> &storedObjects)
Read the selected GeometricFields of the templated type and store on the objectRegistry.
A class for handling words, derived from Foam::string.
Definition: word.H:63
#define DebugInFunction
Report an information message using Foam::Info.
bool returnReduceAnd(const bool value, const int communicator=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
void storeOldTime() const
Store the old-time field.
bool local
Definition: EEqn.H:20
errorManip< error > abort(error &err)
Definition: errorManip.H:139
Us boundaryFieldRef().evaluateCoupled< coupledFaPatch >()
void negate()
Negate the field inplace. See notes in Field.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
const direction noexcept
Definition: scalarImpl.H:255
Internal & internalFieldRef(const bool updateAccessTime=true)
Return a reference to the dimensioned internal field.
tmp< GeometricField< Type, PatchField, GeoMesh > > T() const
Return transpose (only if it is a tensor field)
int debug
Static debugging option.
void normalise()
Normalise the field inplace. See notes in Field.
const GeometricField< Type, PatchField, GeoMesh > & prevIter() const
Return previous iteration field.
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
const dimensionSet & dimensions() const noexcept
Return dimensions.
virtual ~GeometricField()
Destructor.
Generic GeometricBoundaryField class.
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))
void clamp_max(const Type &upper)
Impose upper (ceiling) clamp on the field values (in-place)
List< word > wordList
List of word.
Definition: fileName.H:59
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field values.
tmp< GeometricField< Type, PatchField, GeoMesh > > clone() const
Clone.
#define WarningInFunction
Report a warning using Foam::Warning.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:54
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
meshDefDict readIfPresent("polyMeshPatches", polyPatchNames)
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
void correctBoundaryConditions()
Correct boundary field.
messageStream Info
Information stream (stdout output on master, null elsewhere)
void storePrevIter() const
Store the field as the previous iteration value.
Generic mesh wrapper used by volMesh, surfaceMesh, pointMesh etc.
Definition: GeoMesh.H:45
List< label > labelList
A List of labels.
Definition: List.H:61
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
A class for managing temporary objects.
Definition: HashPtrTable.H:50
tmp< faMatrix< Type > > operator==(const faMatrix< Type > &, const faMatrix< Type > &)
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
void relax()
Relax field (for steady-state solution).
void correctLocalBoundaryConditions()
Correct boundary conditions after a purely local operation.
label timeIndex
Definition: getTimeIndex.H:24
#define checkField(fld1, fld2, op)
#define InfoInFunction
Report an information message using Foam::Info.
void replace(const direction d, const GeometricField< cmptType, PatchField, GeoMesh > &gcf)
Replace specified field component with content from another field.