surfaceDisplacementPointPatchVectorField.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) 2011-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 
28 #include "Time.H"
29 #include "transformField.H"
32 
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37 
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 const NamedEnum<surfaceDisplacementPointPatchVectorField::projectMode, 3>
42 surfaceDisplacementPointPatchVectorField::projectModeNames_
43 {
44  "nearest",
45  "pointNormal",
46  "fixedNormal"
47 };
48 
49 
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
51 
52 void surfaceDisplacementPointPatchVectorField::calcProjection
53 (
54  vectorField& displacement
55 ) const
56 {
57  const polyMesh& mesh = patch().mesh()();
58  const pointField& localPoints = patch().localPoints();
59  const labelList& meshPoints = patch().meshPoints();
60 
61  // const scalar deltaT = mesh.time().deltaTValue();
62 
63  // Construct large enough vector in direction of projectDir so
64  // we're guaranteed to hit something.
65 
66  //- Per point projection vector:
67  const scalar projectLen = mag(mesh.bounds().max()-mesh.bounds().min());
68 
69  // For case of fixed projection vector:
70  vector projectVec(Zero);
71  if (projectMode_ == FIXEDNORMAL)
72  {
73  vector n = projectDir_/mag(projectDir_);
74  projectVec = projectLen*n;
75  }
76 
77 
78  // Get fixed points (bit of a hack)
79  const pointZone* zonePtr = nullptr;
80 
81  if (frozenPointsZone_.size() > 0)
82  {
83  const pointZoneList& pZones = mesh.pointZones();
84 
85  zonePtr = &pZones[frozenPointsZone_];
86 
87  Pout<< "surfaceDisplacementPointPatchVectorField : Fixing all "
88  << zonePtr->size() << " points in pointZone " << zonePtr->name()
89  << endl;
90  }
91 
92  // Get the starting locations from the pointMeshMover
93  const pointField& points0 =
94  refCast<const pointMeshMovers::displacement>
95  (refCast<const fvMesh>(mesh).mover()).points0();
96 
97  pointField start(meshPoints.size());
98  forAll(start, i)
99  {
100  start[i] = points0[meshPoints[i]] + displacement[i];
101  }
102 
103  label nNotProjected = 0;
104 
105  if (projectMode_ == NEAREST)
106  {
107  List<pointIndexHit> nearest;
108  labelList hitSurfaces;
110  (
111  start,
112  scalarField(start.size(), sqr(projectLen)),
113  hitSurfaces,
114  nearest
115  );
116 
117  forAll(nearest, i)
118  {
119  if (zonePtr && (zonePtr->localIndex(meshPoints[i]) >= 0))
120  {
121  // Fixed point. Reset to point0 location.
122  displacement[i] = points0[meshPoints[i]] - localPoints[i];
123  }
124  else if (nearest[i].hit())
125  {
126  displacement[i] =
127  nearest[i].hitPoint()
128  - points0[meshPoints[i]];
129  }
130  else
131  {
132  nNotProjected++;
133 
134  if (debug)
135  {
136  Pout<< " point:" << meshPoints[i]
137  << " coord:" << localPoints[i]
138  << " did not find any surface within " << projectLen
139  << endl;
140  }
141  }
142  }
143  }
144  else
145  {
146  // Do tests on all points. Combine later on.
147 
148  // 1. Check if already on surface
149  List<pointIndexHit> nearest;
150  {
151  labelList nearestSurface;
153  (
154  start,
155  scalarField(start.size(), sqr(small)),
156  nearestSurface,
157  nearest
158  );
159  }
160 
161  // 2. intersection. (combined later on with information from nearest
162  // above)
163  vectorField projectVecs(start.size(), projectVec);
164 
165  if (projectMode_ == POINTNORMAL)
166  {
167  projectVecs = projectLen*patch().pointNormals();
168  }
169 
170  // Knock out any wedge component
171  scalarField offset(start.size(), 0.0);
172  if (wedgePlane_ >= 0 && wedgePlane_ <= vector::nComponents)
173  {
174  forAll(offset, i)
175  {
176  offset[i] = start[i][wedgePlane_];
177  start[i][wedgePlane_] = 0;
178  projectVecs[i][wedgePlane_] = 0;
179  }
180  }
181 
182  List<pointIndexHit> rightHit;
183  {
184  labelList rightSurf;
186  (
187  start,
188  start+projectVecs,
189  rightSurf,
190  rightHit
191  );
192  }
193 
194  List<pointIndexHit> leftHit;
195  {
196  labelList leftSurf;
198  (
199  start,
200  start-projectVecs,
201  leftSurf,
202  leftHit
203  );
204  }
205 
206  // 3. Choose either -fixed, nearest, right, left.
207  forAll(displacement, i)
208  {
209  if (zonePtr && (zonePtr->localIndex(meshPoints[i]) >= 0))
210  {
211  // Fixed point. Reset to point0 location.
212  displacement[i] = points0[meshPoints[i]] - localPoints[i];
213  }
214  else if (nearest[i].hit())
215  {
216  // Found nearest.
217  displacement[i] =
218  nearest[i].hitPoint()
219  - points0[meshPoints[i]];
220  }
221  else
222  {
223  pointIndexHit interPt;
224 
225  if (rightHit[i].hit())
226  {
227  if (leftHit[i].hit())
228  {
229  if
230  (
231  magSqr(rightHit[i].hitPoint()-start[i])
232  < magSqr(leftHit[i].hitPoint()-start[i])
233  )
234  {
235  interPt = rightHit[i];
236  }
237  else
238  {
239  interPt = leftHit[i];
240  }
241  }
242  else
243  {
244  interPt = rightHit[i];
245  }
246  }
247  else
248  {
249  if (leftHit[i].hit())
250  {
251  interPt = leftHit[i];
252  }
253  }
254 
255 
256  if (interPt.hit())
257  {
258  if (wedgePlane_ >= 0 && wedgePlane_ <= vector::nComponents)
259  {
260  interPt.rawPoint()[wedgePlane_] += offset[i];
261  }
262  displacement[i] = interPt.rawPoint()-points0[meshPoints[i]];
263  }
264  else
265  {
266  nNotProjected++;
267 
268  if (debug)
269  {
270  Pout<< " point:" << meshPoints[i]
271  << " coord:" << localPoints[i]
272  << " did not find any intersection between"
273  << " ray from " << start[i]-projectVecs[i]
274  << " to " << start[i]+projectVecs[i] << endl;
275  }
276  }
277  }
278  }
279  }
280 
281  reduce(nNotProjected, sumOp<label>());
282 
283  if (nNotProjected > 0)
284  {
285  Info<< "surfaceDisplacement :"
286  << " on patch " << patch().name()
287  << " did not project " << nNotProjected
288  << " out of " << returnReduce(localPoints.size(), sumOp<label>())
289  << " points." << endl;
290  }
291 }
292 
293 
294 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
295 
298 (
299  const pointPatch& p,
301  const dictionary& dict
302 )
303 :
304  fixedValuePointPatchVectorField(p, iF, dict),
305  velocity_(dict.lookup<vector>("velocity", dimVelocity)),
306  surfacesDict_(dict.subDict("geometry")),
307  projectMode_(projectModeNames_.read(dict.lookup("projectMode"))),
308  projectDir_(dict.lookup<vector>("projectDirection", dimless)),
309  wedgePlane_(dict.lookupOrDefault("wedgePlane", -1)),
310  frozenPointsZone_(dict.lookupOrDefault("frozenPointsZone", word::null))
311 {
312  if (velocity_.x() < 0 || velocity_.y() < 0 || velocity_.z() < 0)
313  {
315  << "All components of velocity have to be positive : "
316  << velocity_ << nl
317  << "Set velocity components to a great value if no clipping"
318  << " necessary." << exit(FatalError);
319  }
320 }
321 
322 
325 (
327  const pointPatch& p,
329  const fieldMapper& mapper
330 )
331 :
332  fixedValuePointPatchVectorField(ppf, p, iF, mapper),
333  velocity_(ppf.velocity_),
334  surfacesDict_(ppf.surfacesDict_),
335  projectMode_(ppf.projectMode_),
336  projectDir_(ppf.projectDir_),
337  wedgePlane_(ppf.wedgePlane_),
338  frozenPointsZone_(ppf.frozenPointsZone_)
339 {}
340 
341 
344 (
347 )
348 :
349  fixedValuePointPatchVectorField(ppf, iF),
350  velocity_(ppf.velocity_),
351  surfacesDict_(ppf.surfacesDict_),
352  projectMode_(ppf.projectMode_),
353  projectDir_(ppf.projectDir_),
354  wedgePlane_(ppf.wedgePlane_),
355  frozenPointsZone_(ppf.frozenPointsZone_)
356 {}
357 
358 
359 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
360 
363 {
364  if (surfacesPtr_.empty())
365  {
366  surfacesPtr_.reset
367  (
369  (
370  IOobject
371  (
372  "abc", // dummy name
373  time().constant(),
375  time(),
378  ),
379  surfacesDict_,
380  true // allow single-region shortcut
381  )
382  );
383  }
384  return surfacesPtr_();
385 }
386 
387 
389 {
390  if (this->updated())
391  {
392  return;
393  }
394 
395  const polyMesh& mesh = patch().mesh()();
396 
397  vectorField currentDisplacement(this->patchInternalField());
398 
399  // Calculate intersections with surface w.r.t points0.
400  vectorField displacement(currentDisplacement);
401  calcProjection(displacement);
402 
403  // offset wrt current displacement
404  vectorField offset(displacement-currentDisplacement);
405 
406  // Clip offset to maximum displacement possible: velocity*timestep
407 
408  const scalar deltaT = mesh.time().deltaTValue();
409  const vector clipVelocity = velocity_*deltaT;
410 
411  forAll(displacement, i)
412  {
413  vector& d = offset[i];
414 
415  for (direction cmpt = 0; cmpt < vector::nComponents; cmpt++)
416  {
417  if (d[cmpt] < 0)
418  {
419  d[cmpt] = max(d[cmpt], -clipVelocity[cmpt]);
420  }
421  else
422  {
423  d[cmpt] = min(d[cmpt], clipVelocity[cmpt]);
424  }
425  }
426  }
427 
428  this->operator==(currentDisplacement+offset);
429 
430  fixedValuePointPatchVectorField::updateCoeffs();
431 }
432 
433 
435 {
437  writeEntry(os, "velocity", velocity_);
438  writeEntry(os, "geometry", surfacesDict_);
439  writeEntry(os, "projectMode", projectModeNames_[projectMode_]);
440  writeEntry(os, "projectDirection", projectDir_);
441  writeEntry(os, "wedgePlane", wedgePlane_);
442  if (frozenPointsZone_ != word::null)
443  {
444  writeEntry(os, "frozenPointsZone", frozenPointsZone_);
445  }
446 }
447 
448 
449 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
450 
452 (
453  fixedValuePointPatchVectorField,
455 );
456 
457 
458 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
459 
460 } // End namespace Foam
461 
462 // ************************************************************************* //
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Macros for easy insertion into run-time selection tables.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
virtual const fileName & name() const
Return the name of the stream.
Definition: OSstream.H:85
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
scalar deltaTValue() const
Return time step value.
Definition: TimeStateI.H:34
static const direction nComponents
Number of components in this vector space.
Definition: VectorSpace.H:105
const Cmpt & z() const
Definition: VectorI.H:87
const Cmpt & y() const
Definition: VectorI.H:81
const Cmpt & x() const
Definition: VectorI.H:75
const point & min() const
Minimum point defining the bounding box.
Definition: boundBoxI.H:88
const point & max() const
Maximum point defining the bounding box.
Definition: boundBoxI.H:94
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
Abstract base class for field mapping.
Definition: fieldMapper.H:48
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:433
Motion of the mesh specified as a list of pointMeshMovers.
Basic pointPatch represents a set of points from the mesh.
Definition: pointPatch.H:61
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:78
const pointZoneList & pointZones() const
Return point zones.
Definition: polyMesh.H:426
const boundBox & bounds() const
Return mesh bounding box.
Definition: polyMesh.H:399
Container for searchableSurfaces.
void findAnyIntersection(const pointField &start, const pointField &end, labelList &surfaces, List< pointIndexHit > &) const
Find any intersection. Return hit point information and.
void findNearest(const pointField &, const scalarField &nearestDistSqr, labelList &surfaces, List< pointIndexHit > &) const
Find nearest. Return -1 (and a miss()) or surface and nearest.
static const word & geometryDir()
Return the geometry directory name.
Displacement fixed by projection onto triSurface. Use in a pointMeshMovers::displacement as a bc on t...
const searchableSurfaceList & surfaces() const
Surface to follow. Demand loads surfaceNames.
surfaceDisplacementPointPatchVectorField(const pointPatch &, const DimensionedField< vector, pointMesh > &, const dictionary &)
Construct from patch, internal field and dictionary.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
A class for handling words, derived from string.
Definition: word.H:63
static const word null
An empty word.
Definition: word.H:78
IOporosityModelList pZones(mesh)
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
const dimensionSet time
const unitSet & lookup(const word &unitName)
Lookup and return the named unit from the table.
Definition: units.C:346
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const zero Zero
Definition: zero.H:97
makePointPatchTypeField(pointPatchVectorField, angularOscillatingDisplacementPointPatchVectorField)
const dimensionSet & dimless
Definition: dimensions.C:138
bool read(const char *, int32_t &)
Definition: int32IO.C:85
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
tmp< fvMatrix< Type > > operator==(const fvMatrix< Type > &, const fvMatrix< Type > &)
PointIndexHit< point > pointIndexHit
Definition: pointIndexHit.H:42
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
messageStream Info
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
tmp< DimensionedField< typename outerProduct< Type, Type >::type, GeoMesh, Field >> sqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
const dimensionSet & dimVelocity
Definition: dimensions.C:154
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
Field< vector > vectorField
Specialisation of Field<T> for vector.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
error FatalError
void offset(label &lst, const label o)
tmp< DimensionedField< scalar, GeoMesh, Field > > magSqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
void writeEntry(Ostream &os, const word &key, const DimensionedFieldFunction< DimensionedFieldType > &f)
static const char nl
Definition: Ostream.H:297
uint8_t direction
Definition: direction.H:45
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dictionary dict
volScalarField & p
Spatial transformation functions for primitive fields.