LagrangianPatchField.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2025-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "LagrangianPatch.H"
27 #include "LagrangianPatchField.H"
28 #include "LagrangianMesh.H"
29 #include "LagrangianSubFields.H"
30 #include "dictionary.H"
31 
32 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
33 
34 template<class Type>
36 (
37  const LagrangianPatch& p,
38  const regIOobject& iIo
39 )
40 :
41  patch_(p),
42  internalIo_(iIo),
43  internalField_
44  (
46  ),
47  internalNonDynamicField_
48  (
49  refCastNull<const LagrangianInternalField<Type>>(iIo)
50  )
51 {}
52 
53 
54 template<class Type>
56 (
57  const LagrangianPatch& p,
58  const regIOobject& iIo,
59  const dictionary&
60 )
61 :
62  patch_(p),
63  internalIo_(iIo),
64  internalField_
65  (
67  ),
68  internalNonDynamicField_
69  (
70  refCastNull<const LagrangianInternalField<Type>>(iIo)
71  )
72 {}
73 
74 
75 template<class Type>
77 (
79 )
80 :
81  patch_(ptf.patch_),
82  internalIo_(ptf.internalIo_),
83  internalField_(ptf.internalField_),
84  internalNonDynamicField_(ptf.internalNonDynamicField_)
85 {}
86 
87 
88 template<class Type>
90 (
91  const LagrangianPatchField<Type>& ptf,
92  const regIOobject& iIo
93 )
94 :
95  patch_(ptf.patch_),
96  internalIo_(iIo),
97  internalField_
98  (
100  ),
101  internalNonDynamicField_
102  (
103  refCastNull<const LagrangianInternalField<Type>>(iIo)
104  )
105 {}
106 
107 
108 template<class Type>
110 (
111  const LagrangianPatchField<Type>& ptf,
112  const LagrangianPatch& p,
113  const regIOobject& iIo
114 )
115 :
116  patch_(p),
117  internalIo_(iIo),
118  internalField_
119  (
121  ),
122  internalNonDynamicField_
123  (
124  refCastNull<const LagrangianInternalField<Type>>(iIo)
125  )
126 {}
127 
128 
129 // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
130 
131 template<class Type>
134 (
135  const word& patchFieldType,
136  const word& actualPatchType,
137  const LagrangianPatch& p,
138  const regIOobject& iIo
139 )
140 {
141  if (debug)
142  {
143  InfoInFunction << "Constructing LagrangianPatchField<Type>" << endl;
144  }
145 
146  typename LagrangianPatchConstructorTable::iterator cstrIter =
147  LagrangianPatchConstructorTablePtr_->find(patchFieldType);
148 
149  if (cstrIter == LagrangianPatchConstructorTablePtr_->end())
150  {
152  << "Unknown patchField type "
153  << patchFieldType << nl << nl
154  << "Valid patchField types are :" << endl
155  << LagrangianPatchConstructorTablePtr_->sortedToc()
156  << exit(FatalError);
157  }
158 
159  if
160  (
161  actualPatchType == word::null
162  || actualPatchType != p.type()
163  )
164  {
165  typename LagrangianPatchConstructorTable::iterator patchTypeCstrIter =
166  LagrangianPatchConstructorTablePtr_->find(p.type());
167 
168  if (patchTypeCstrIter != LagrangianPatchConstructorTablePtr_->end())
169  {
170  return patchTypeCstrIter()(p, iIo);
171  }
172  else
173  {
174  return cstrIter()(p, iIo);
175  }
176  }
177  else
178  {
179  return cstrIter()(p, iIo);
180  }
181 }
182 
183 
184 template<class Type>
187 (
188  const word& patchFieldType,
189  const LagrangianPatch& p,
190  const regIOobject& iIo
191 )
192 {
193  return New(patchFieldType, word::null, p, iIo);
194 }
195 
196 
197 template<class Type>
200 (
201  const LagrangianPatch& p,
202  const regIOobject& iIo,
203  const dictionary& dict
204 )
205 {
206  if (debug)
207  {
208  InfoInFunction << "Constructing fvsPatchField<Type>" << endl;
209  }
210 
211  const word patchFieldType(dict.lookup("type"));
212 
213  typename dictionaryConstructorTable::iterator cstrIter
214  = dictionaryConstructorTablePtr_->find(patchFieldType);
215 
216  if (cstrIter == dictionaryConstructorTablePtr_->end())
217  {
218  if (!disallowGenericLagrangianPatchField)
219  {
220  cstrIter = dictionaryConstructorTablePtr_->find("generic");
221  }
222 
223  if (cstrIter == dictionaryConstructorTablePtr_->end())
224  {
226  << "Unknown patchField type " << patchFieldType
227  << " for patch type " << p.type() << nl << nl
228  << "Valid patchField types are :" << endl
229  << dictionaryConstructorTablePtr_->sortedToc()
230  << exit(FatalIOError);
231  }
232  }
233 
234  if
235  (
236  !dict.found("patchType")
237  || word(dict.lookup("patchType")) != p.type()
238  )
239  {
240  typename dictionaryConstructorTable::iterator patchTypeCstrIter
241  = dictionaryConstructorTablePtr_->find(p.type());
242 
243  if
244  (
245  patchTypeCstrIter != dictionaryConstructorTablePtr_->end()
246  && patchTypeCstrIter() != cstrIter()
247  )
248  {
250  (
251  dict
252  ) << "inconsistent patch and patchField types for \n"
253  " patch type " << p.type()
254  << " and patchField type " << patchFieldType
255  << exit(FatalIOError);
256  }
257  }
258 
259  return cstrIter()(p, iIo, dict);
260 }
261 
262 
263 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
264 
265 template<class Type>
267 {}
268 
269 
270 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
271 
272 template<class Type>
274 {
275  return patch_.boundaryMesh().mesh();
276 }
277 
278 
279 template<class Type>
281 {
282  return patch_.boundaryMesh().mesh().time();
283 }
284 
285 
286 template<class Type>
288 {
289  return patch_;
290 }
291 
292 
293 template<class Type>
294 const Foam::dimensionSet&
296 {
297  if (notNull(internalField_))
298  {
299  return internalField_.dimensions();
300  }
301 
302  if (notNull(internalNonDynamicField_))
303  {
304  return internalNonDynamicField_.dimensions();
305  }
306 
308  << "Dimensions of internal object " << internalIo_.name()
309  << " could not be determined"
310  << exit(FatalError);
311 
312  return NullObjectRef<dimensionSet>();
313 }
314 
315 
316 template<class Type>
319 {
320  if (notNull(internalField_))
321  {
322  return internalField_;
323  }
324 
326  << "Internal field " << internalIo_.name() << " is not of type "
328  << exit(FatalError);
329 
330  return NullObjectRef<LagrangianInternalDynamicField<Type>>();
331 }
332 
333 
334 template<class Type>
337 {
338  if (notNull(internalField_))
339  {
340  return patch_.mesh().sub(internalField_);
341  }
342 
343  if (notNull(internalNonDynamicField_))
344  {
345  return patch_.mesh().sub(internalNonDynamicField_);
346  }
347 
349  << "Internal field " << internalIo_.name() << " is not of type "
351  << exit(FatalError);
352 
353  return tmp<LagrangianSubSubField<Type>>(nullptr);
354 }
355 
356 
357 template<class Type>
359 {
360  if (notNull(internalField_))
361  {
362  return patch_.mesh().sub(internalField_.primitiveField());
363  }
364 
365  if (notNull(internalNonDynamicField_))
366  {
367  return patch_.mesh().sub(internalNonDynamicField_.primitiveField());
368  }
369 
371  << "Internal field " << internalIo_.name() << " is not of type "
373  << exit(FatalError);
374 
375  return SubField<Type>(NullObjectRef<UList<Type>>(), 0, 0);
376 }
377 
378 
379 template<class Type>
381 {}
382 
383 
384 template<class Type>
386 (
389 )
390 {}
391 
392 
393 template<class Type>
395 (
398 )
399 {}
400 
401 
402 template<class Type>
404 {
405  writeEntry(os, "type", type());
406 }
407 
408 
409 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
410 
411 template<class Type>
414 {
415  return internalSubField();
416 }
417 
418 
419 #define MEMBER_OPERATOR(MemberOp, FieldOp, OtherType, OtherDimensions) \
420  \
421 template<class Type> \
422 void Foam::LagrangianPatchField<Type>::operator MemberOp \
423 ( \
424  const LagrangianPatchField<OtherType>& ptf \
425 ) \
426 { \
427  if (&patch_ != &(ptf.patch_)) \
428  { \
429  FatalErrorInFunction \
430  << "different patches for LagrangianPatchField<Type>s" \
431  << abort(FatalError); \
432  } \
433  \
434  if (!patch_.boundaryMesh().mesh().changing()) return; \
435  \
436  OtherDimensions == ptf.internalDimensions(); \
437  \
438  LagrangianSubSubField<Type> thisSsf(internalSubField()); \
439  thisSsf FieldOp ptf.internalSubField(); \
440 } \
441  \
442 template<class Type> \
443 void Foam::LagrangianPatchField<Type>::operator MemberOp \
444 ( \
445  const LagrangianSubField<OtherType>& sf \
446 ) \
447 { \
448  if (!patch_.boundaryMesh().mesh().changing()) return; \
449  \
450  OtherDimensions == sf.dimensions(); \
451  \
452  SubField<Type> thisSf(primitiveSubField()); \
453  thisSf FieldOp sf.primitiveField(); \
454 } \
455  \
456 template<class Type> \
457 void Foam::LagrangianPatchField<Type>::operator MemberOp \
458 ( \
459  const LagrangianSubSubField<OtherType>& ssf \
460 ) \
461 { \
462  if (!patch_.boundaryMesh().mesh().changing()) return; \
463  \
464  OtherDimensions == ssf.dimensions(); \
465  \
466  SubField<Type> thisSf(primitiveSubField()); \
467  thisSf FieldOp ssf.primitiveField(); \
468 } \
469  \
470 template<class Type> \
471 void Foam::LagrangianPatchField<Type>::operator MemberOp \
472 ( \
473  const UList<OtherType>& f \
474 ) \
475 { \
476  if (!patch_.boundaryMesh().mesh().changing()) return; \
477  \
478  SubField<Type> thisSf(primitiveSubField()); \
479  thisSf FieldOp f; \
480 } \
481  \
482 template<class Type> \
483 void Foam::LagrangianPatchField<Type>::operator MemberOp(const OtherType& t) \
484 { \
485  if (!patch_.boundaryMesh().mesh().changing()) return; \
486  \
487  SubField<Type> thisSf(primitiveSubField()); \
488  thisSf FieldOp t; \
489 }
490 
491 MEMBER_OPERATOR(=, =, Type, internalDimensions());
492 MEMBER_OPERATOR(==, =, Type, internalDimensions());
493 MEMBER_OPERATOR(+=, +=, Type, internalDimensions());
494 MEMBER_OPERATOR(-=, -=, Type, internalDimensions());
495 MEMBER_OPERATOR(*=, *=, scalar, dimless);
496 MEMBER_OPERATOR(/=, /=, scalar, dimless);
497 
498 #undef MEMBER_OPERATOR
499 
500 
501 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
502 
503 template<class Type>
504 Foam::Ostream& Foam::operator<<
505 (
506  Ostream& os,
507  const LagrangianPatchField<Type>& ptf
508 )
509 {
510  ptf.write(os);
511 
512  os.check
513  (
514  "Ostream& operator<<(Ostream&, const LagrangianPatchField<Type>&)"
515  );
516 
517  return os;
518 }
519 
520 
521 // ************************************************************************* //
#define MEMBER_OPERATOR(MemberOp, FieldOp, OtherType, OtherDimensions)
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:108
Base class for Lagrangian boundary conditions.
virtual ~LagrangianPatchField()
Destructor.
static autoPtr< LagrangianPatchField< Type > > New(const word &patchFieldType, const word &actualPatchType, const LagrangianPatch &p, const regIOobject &)
Return a pointer to a new LagrangianPatchField with a given type.
const dimensionSet & internalDimensions() const
Return internal dimensions reference.
tmp< LagrangianSubSubField< Type > > operator()() const
Generate a sub-sub field corresponding to this patch.
const Time & time() const
Return time.
virtual void write(Ostream &) const
Write.
virtual void reset(const LagrangianPatchField< Type > &)
Reset to the given LagrangianPatchField.
const LagrangianPatch & patch() const
Return patch.
const objectRegistry & db() const
Return local objectRegistry.
virtual void initEvaluate(PstreamBuffers &, const LagrangianInternalScalarDynamicField &fraction)
Initialise evaluation of the patch field.
friend class LagrangianPatchField
Declare friendship with patch fields of different types.
tmp< LagrangianSubSubField< Type > > internalSubField() const
Generate an internal sub field corresponding to this patch.
virtual void evaluate(PstreamBuffers &, const LagrangianInternalScalarDynamicField &fraction)
Evaluate the patch field.
SubField< Type > primitiveSubField() const
Generate a primitive sub field corresponding to this patch.
const LagrangianInternalDynamicField< Type > & internalField() const
Return internal field reference.
Base class for Lagrangian patches.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
virtual Ostream & write(const token &)
Write token.
Definition: Ostream.C:51
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Pre-declare related SubField type.
Definition: SubField.H:63
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:76
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:669
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:468
Dimension set for the base types.
Definition: dimensionSet.H:125
Registry of regIOobjects.
const Time & time() const
Return time.
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:55
A class for managing temporary objects.
Definition: tmp.H:55
A class for handling words, derived from string.
Definition: word.H:63
static const word null
An empty word.
Definition: word.H:78
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
#define InfoInFunction
Report an information message using Foam::Info.
const unitSet fraction
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
To & refCastNull(From &r)
Reference type cast template function,.
Definition: typeInfo.H:162
const dimensionSet & dimless
Definition: dimensions.C:138
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
bool notNull(const T &t)
Return true if t is not a reference to the nullObject of type T.
Definition: nullObjectI.H:64
const T & NullObjectRef()
Return const reference to the nullObject of type T.
Definition: nullObjectI.H:27
word patchFieldType(const PatchField &pf)
IOerror FatalIOError
error FatalError
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
void writeEntry(Ostream &os, const word &key, const DimensionedFieldFunction< DimensionedFieldType > &f)
static const char nl
Definition: Ostream.H:297
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
dictionary dict
volScalarField & p