surfaceSlipDisplacementPointPatchVectorField.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-2016 OpenFOAM Foundation
9  Copyright (C) 2020-2022,2024 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 
31 #include "Time.H"
32 #include "transformField.H"
33 #include "fvMesh.H"
35 #include "facePointPatch.H"
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 const Foam::Enum
40 <
42 >
43 Foam::surfaceSlipDisplacementPointPatchVectorField::projectModeNames_
44 ({
45  { projectMode::NEAREST, "nearest" },
46  { projectMode::POINTNORMAL, "pointNormal" },
47  { projectMode::FIXEDNORMAL, "fixedNormal" },
48 });
49 
50 
51 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 
53 void Foam::surfaceSlipDisplacementPointPatchVectorField::calcProjection
54 (
55  vectorField& displacement
56 ) const
57 {
58  const polyMesh& mesh = patch().boundaryMesh().mesh()();
59  const pointField& localPoints = patch().localPoints();
60  const labelList& meshPoints = patch().meshPoints();
61 
62  //const scalar deltaT = mesh.time().deltaTValue();
63 
64  // Construct large enough vector in direction of projectDir so
65  // we're guaranteed to hit something.
66 
67  //- Per point projection vector:
68  const scalar projectLen = mesh.bounds().mag();
69 
70  // For case of fixed projection vector:
71  vector projectVec(Zero);
72  if (projectMode_ == FIXEDNORMAL)
73  {
74  projectVec = projectLen * normalised(projectDir_);
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 pointZoneMesh& pZones = mesh.pointZones();
84 
85  zonePtr = &pZones[frozenPointsZone_];
86 
87  Pout<< "surfaceSlipDisplacementPointPatchVectorField : Fixing all "
88  << zonePtr->size() << " points in pointZone " << zonePtr->name()
89  << endl;
90  }
91 
92  // Get the starting locations from the motionSolver
93  const pointField& points0 = mesh.lookupObject<displacementMotionSolver>
94  (
95  "dynamicMeshDict"
96  ).points0();
97 
98 
99  pointField start(meshPoints.size());
100  forAll(start, i)
101  {
102  start[i] = points0[meshPoints[i]] + displacement[i];
103  }
104 
105  label nNotProjected = 0;
106 
107  if (projectMode_ == NEAREST)
108  {
109  List<pointIndexHit> nearest;
110  labelList hitSurfaces;
112  (
113  start,
114  scalarField(start.size(), sqr(projectLen)),
115  hitSurfaces,
116  nearest
117  );
118 
119  forAll(nearest, i)
120  {
121  if (zonePtr && (zonePtr->whichPoint(meshPoints[i]) >= 0))
122  {
123  // Fixed point. Reset to point0 location.
124  displacement[i] = points0[meshPoints[i]] - localPoints[i];
125  }
126  else if (nearest[i].hit())
127  {
128  displacement[i] = nearest[i].point() - 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(), Zero);
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->whichPoint(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] = nearest[i].point() - points0[meshPoints[i]];
218  }
219  else
220  {
221  pointIndexHit interPt;
222 
223  if (rightHit[i].hit())
224  {
225  if
226  (
227  !leftHit[i].hit()
228  ||
229  (
230  start[i].distSqr(rightHit[i].point())
231  < start[i].distSqr(leftHit[i].point())
232  )
233  )
234  {
235  interPt = rightHit[i];
236  }
237  else
238  {
239  interPt = leftHit[i];
240  }
241  }
242  else
243  {
244  if (leftHit[i].hit())
245  {
246  interPt = leftHit[i];
247  }
248  }
249 
250 
251  if (interPt.hit())
252  {
253  if (wedgePlane_ >= 0 && wedgePlane_ < vector::nComponents)
254  {
255  interPt.point()[wedgePlane_] += offset[i];
256  }
257  displacement[i] = interPt.point() - points0[meshPoints[i]];
258  }
259  else
260  {
261  nNotProjected++;
262 
263  if (debug)
264  {
265  Pout<< " point:" << meshPoints[i]
266  << " coord:" << localPoints[i]
267  << " did not find any intersection between"
268  << " ray from " << start[i]-projectVecs[i]
269  << " to " << start[i]+projectVecs[i] << endl;
270  }
271  }
272  }
273  }
274  }
275 
276  if (scalePtr_)
277  {
278  const scalarField s
279  (
280  scalePtr_->value(this->db().time().timeOutputValue())
281  );
282 
283  displacement *= s;
284  }
285 
286  reduce(nNotProjected, sumOp<label>());
287 
288  if (nNotProjected > 0)
289  {
290  Info<< "surfaceSlipDisplacement :"
291  << " on patch " << patch().name()
292  << " did not project " << nNotProjected
293  << " out of " << returnReduce(localPoints.size(), sumOp<label>())
294  << " points." << endl;
295  }
296 }
297 
299 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
300 
303 (
304  const pointPatch& p,
306 )
307 :
309  projectMode_(NEAREST),
310  projectDir_(Zero),
311  wedgePlane_(-1)
312 {}
313 
314 
317 (
318  const pointPatch& p,
320  const dictionary& dict
321 )
322 :
324  surfacesDict_(dict.subDict("geometry")),
325  projectMode_(projectModeNames_.get("projectMode", dict)),
326  projectDir_
327  (
328  (projectMode_ == FIXEDNORMAL)
329  ? dict.get<vector>("projectDirection")
330  : Zero
331  ),
332  wedgePlane_(dict.getOrDefault("wedgePlane", -1)),
333  frozenPointsZone_(dict.getOrDefault("frozenPointsZone", word::null)),
334  scalePtr_
335  (
336  PatchFunction1<scalar>::NewIfPresent
337  (
338  refCast<const facePointPatch>(p).patch(),
339  "scale",
340  dict,
341  false // point values
342  )
343  )
344 {}
345 
346 
349 (
351  const pointPatch& p,
353  const pointPatchFieldMapper&
354 )
355 :
357  surfacesDict_(ppf.surfacesDict_),
358  projectMode_(ppf.projectMode_),
359  projectDir_(ppf.projectDir_),
360  wedgePlane_(ppf.wedgePlane_),
361  frozenPointsZone_(ppf.frozenPointsZone_),
362  scalePtr_(ppf.scalePtr_.clone(refCast<const facePointPatch>(p).patch()))
363 {}
364 
365 
368 (
370 )
371 :
373  surfacesDict_(ppf.surfacesDict_),
374  projectMode_(ppf.projectMode_),
375  projectDir_(ppf.projectDir_),
376  wedgePlane_(ppf.wedgePlane_),
377  frozenPointsZone_(ppf.frozenPointsZone_),
378  scalePtr_
379  (
380  ppf.scalePtr_.clone
381  (
382  refCast<const facePointPatch>(ppf.patch()).patch()
383  )
384  )
385 {}
386 
387 
390 (
393 )
394 :
395  pointPatchVectorField(ppf, iF),
396  surfacesDict_(ppf.surfacesDict_),
397  projectMode_(ppf.projectMode_),
398  projectDir_(ppf.projectDir_),
399  wedgePlane_(ppf.wedgePlane_),
400  frozenPointsZone_(ppf.frozenPointsZone_),
401  scalePtr_
402  (
403  ppf.scalePtr_.clone
404  (
405  refCast<const facePointPatch>(ppf.patch()).patch()
406  )
407  )
408 {}
410 
411 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
412 
415 {
416  if (!surfacesPtr_)
417  {
418  surfacesPtr_.reset
419  (
421  (
422  IOobject
423  (
424  "abc", // dummy name
425  db().time().constant(), // directory
426  "triSurface", // instance
427  db().time(), // registry
430  ),
431  surfacesDict_,
432  true // use single region naming shortcut
433  )
434  );
435  }
437  return *surfacesPtr_;
438 }
439 
440 
442 {
443  if (this->updated())
444  {
445  return;
446  }
447 
448  vectorField displacement(this->patchInternalField());
449 
450  // Calculate displacement to project points onto surface
451  calcProjection(displacement);
452 
453  if (debug)
454  {
455  Pout<< type() << " :"
456  << " on patch " << patch().name()
457  << " of field " << this->internalField().name()
458  << " projection"
459  << " min:" << gMin(displacement)
460  << " max:" << gMaxMagSqr(displacement)
461  << " average:" << gAverage(displacement)
462  << endl;
463  }
464 
465  // Get internal field to insert values into
466  Field<vector>& iF = const_cast<Field<vector>&>(this->primitiveField());
467 
468  //setInInternalField(iF, motionU);
469  setInInternalField(iF, displacement);
470 
472 }
473 
474 
476 (
477  Ostream& os
478 ) const
479 {
481  os.writeEntry("geometry", surfacesDict_);
482  os.writeEntry("projectMode", projectModeNames_[projectMode_]);
484  (
485  "projectDirection",
486  Zero,
487  projectDir_
488  );
489  os.writeEntryIfDifferent<label>("wedgePlane", -1, wedgePlane_);
491  (
492  "frozenPointsZone",
493  word::null,
494  frozenPointsZone_
495  );
496 
497  if (scalePtr_)
498  {
499  scalePtr_->writeData(os);
500  }
501 }
502 
503 
504 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
505 
506 namespace Foam
507 {
508 
510 (
512  surfaceSlipDisplacementPointPatchVectorField
513 );
514 
515 } // End namespace Foam
516 
517 // ************************************************************************* //
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
dictionary dict
Displacement follows a triSurface. Use in a displacementMotionSolver as a bc on the pointDisplacement...
const pointPatch & patch() const noexcept
Return the patch.
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
Type gMin(const FieldField< Field, Type > &f)
void findAnyIntersection(const pointField &start, const pointField &end, labelList &surfaces, List< pointIndexHit > &) const
Find any intersection. Return hit point information and.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
Definition: typeInfo.H:172
Foam::pointPatchFieldMapper.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
PointIndexHit< point > pointIndexHit
A PointIndexHit with a 3D point.
Definition: pointIndexHit.H:58
virtual void write(Ostream &os) const
Write.
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:321
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept
The number of components associated with given valueTypeCode.
Definition: exprTraits.C:40
Ignore writing from objectRegistry::writeObject()
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
Definition: quaternionI.H:674
virtual const fileName & name() const override
Get the name of the output serial stream. (eg, the name of the Fstream file name) ...
Definition: OSstream.H:134
const pointMesh & mesh() const noexcept
Return the mesh reference.
Macros for easy insertion into run-time selection tables.
void reduce(T &value, [[maybe_unused]] BinaryOp bop, [[maybe_unused]] const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce)
A pointPatch based on a polyPatch.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
Type gMaxMagSqr(const UList< Type > &f, const label comm)
Spatial transformation functions for primitive fields.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:801
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
dynamicFvMesh & mesh
void findNearest(const pointField &, const scalarField &nearestDistSqr, labelList &surfaces, List< pointIndexHit > &) const
Find nearest. Return -1 (and a miss()) or surface and nearest.
A class for handling words, derived from Foam::string.
Definition: word.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
static const word null
An empty word.
Definition: word.H:84
Container for searchableSurfaces. The collection is specified as a dictionary. For example...
T returnReduce(const T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Vector< scalar > vector
Definition: vector.H:57
ZoneMesh< pointZone, polyMesh > pointZoneMesh
A ZoneMesh with the type pointZone.
Ostream & writeEntryIfDifferent(const word &key, const T &value1, const T &value2)
Write a keyword/value entry only when the two values differ.
Definition: Ostream.H:336
const word & name() const noexcept
The patch name.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
Top level data entry class for use in dictionaries. Provides a mechanism to specify a variable as a c...
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
int debug
Static debugging option.
Type gAverage(const FieldField< Field, Type > &f, const label comm)
The global arithmetic average of a FieldField.
OBJstream os(runTime.globalPath()/outputName)
pointPatchField< vector > pointPatchVectorField
virtual const vectorField & pointNormals() const =0
Return point unit normals.
const pointBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
Definition: pointPatch.H:250
virtual const vectorField & localPoints() const =0
Return pointField of points in patch.
pointField points0(pointIOField(IOobject("points", mesh.time().constant(), polyMesh::meshSubDir, mesh, IOobject::MUST_READ, IOobject::NO_WRITE, IOobject::NO_REGISTER)))
vector point
Point is a vector.
Definition: point.H:37
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: error.H:64
Basic pointPatch represents a set of points from the mesh.
Definition: pointPatch.H:64
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
const std::string patch
OpenFOAM patch number as a std::string.
messageStream Info
Information stream (stdout output on master, null elsewhere)
makePointPatchTypeField(pointPatchVectorField, solidBodyMotionDisplacementPointPatchVectorField)
Field< vector > vectorField
Specialisation of Field<T> for vector.
List< label > labelList
A List of labels.
Definition: List.H:61
volScalarField & p
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;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
const searchableSurfaces & surfaces() const
Surface to follow. Demand loads surfaceNames.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
surfaceSlipDisplacementPointPatchVectorField(const pointPatch &, const DimensionedField< vector, pointMesh > &)
Construct from patch and internal field.
Namespace for OpenFOAM.
virtual const labelList & meshPoints() const =0
Return mesh points.
IOporosityModelList pZones(mesh)
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127