edgeSlipDisplacementPointPatchVectorField.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) 2024 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
30 #include "Time.H"
31 #include "transformField.H"
33 #include "featureEdgeMesh.H"
34 
35 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
36 
38 (
39  const objectRegistry& obr,
40  const dictionary& dict
41 )
42 {
43  const Time& tm = obr.time();
44 
45  const fileName featFileName(dict.get<fileName>("file", keyType::LITERAL));
46 
47  if (tm.foundObject<edgeMesh>(featFileName))
48  {
49  return;
50  }
51 
52  IOobject extFeatObj
53  (
54  featFileName, // name
55  tm.constant(), // instance
56  "extendedFeatureEdgeMesh", // local
57  obr, // registry
61  );
62 
63  //const fileName fName(typeFilePath<extendedFeatureEdgeMesh>(extFeatObj));
64  const fileName fName(extFeatObj.typeFilePath<extendedFeatureEdgeMesh>());
65 
66  if (!fName.empty() && extendedEdgeMesh::canRead(fName))
67  {
68  Info<< "Reading edgeMesh from " << extFeatObj.objectRelPath() << endl;
69  auto* eMeshPtr = new extendedFeatureEdgeMesh(extFeatObj);
70  eMeshPtr->store();
71  }
72  else
73  {
74  // Try reading as edgeMesh
75 
76  IOobject featObj
77  (
78  featFileName, // name
79  tm.constant(), // instance
80  "triSurface", // local
81  obr, // registry
85  );
86 
87  Info<< "Reading edgeMesh from " << featObj.objectRelPath() << endl;
88  const fileName fName(featObj.typeFilePath<featureEdgeMesh>());
89 
90  if (fName.empty())
91  {
93  << "Could not open " << featObj.objectPath()
94  << exit(FatalIOError);
95  }
96 
97  // Read as edgeMesh
98  auto* eMeshPtr = new featureEdgeMesh(featObj);
99  eMeshPtr->store();
100  }
101 }
102 
103 
104 void Foam::edgeSlipDisplacementPointPatchVectorField::calcProjection
105 (
106  vectorField& displacement
107 ) const
108 {
109  const polyMesh& mesh = patch().boundaryMesh().mesh()();
110  const labelList& meshPoints = patch().meshPoints();
111 
112  //const scalar deltaT = mesh.time().deltaTValue();
113 
114  // Construct large enough vector in direction of projectDir so
115  // we're guaranteed to hit something.
116 
117  //- Per point projection vector:
118  const scalar projectLen = mesh.bounds().mag();
119 
120 
121 
122  // Get fixed points (bit of a hack)
123  const pointZone* zonePtr = nullptr;
124 
125  if (frozenPointsZone_.size() > 0)
126  {
127  const pointZoneMesh& pZones = mesh.pointZones();
128 
129  zonePtr = &pZones[frozenPointsZone_];
130 
131  Info<< "edgeSlipDisplacementPointPatchVectorField : Fixing all "
132  << zonePtr->size() << " points in pointZone " << zonePtr->name()
133  << endl;
134  }
135 
136  // Get the starting locations from the motionSolver
137  const pointField& points0 = mesh.lookupObject<displacementMotionSolver>
138  (
139  "dynamicMeshDict"
140  ).points0();
141 
142 
143  pointField start(meshPoints.size());
144  forAll(start, i)
145  {
146  start[i] = points0[meshPoints[i]] + displacement[i];
147  }
148 
149  const auto& tree = edgeTree();
150 
151  label nNotProjected = 0;
152  forAll(meshPoints, i)
153  {
154  const label meshPointi = meshPoints[i];
155  const point& pt = mesh.points()[meshPointi];
156 
157  if (zonePtr && (zonePtr->whichPoint(meshPointi) >= 0))
158  {
159  // Fixed point. Reset to point0 location.
160  displacement[i] = points0[meshPointi] - pt;
161  }
162  else
163  {
164  pointIndexHit nearest = tree.findNearest(start[i], sqr(projectLen));
165  if (nearest.hit())
166  {
167  displacement[i] = nearest.point() - points0[meshPointi];
168  }
169  else
170  {
171  nNotProjected++;
172 
173  if (debug)
174  {
175  Pout<< " point:" << meshPointi
176  << " coord:" << pt
177  << " did not find any surface within " << projectLen
178  << endl;
179  }
180  }
181  }
182  }
183 
184  reduce(nNotProjected, sumOp<label>());
185 
186  if (nNotProjected > 0)
187  {
188  Info<< "edgeSlipDisplacement :"
189  << " on patch " << patch().name()
190  << " did not project " << nNotProjected
191  << " out of " << returnReduce(meshPoints.size(), sumOp<label>())
192  << " points." << endl;
193  }
194 }
195 
197 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
198 
201 (
202  const pointPatch& p,
204 )
205 :
207  velocity_(Zero)
208 {}
209 
210 
213 (
214  const pointPatch& p,
216  const dictionary& dict
217 )
218 :
220  velocity_(dict.get<vector>("velocity")),
221  featFileName_(dict.get<fileName>("file", keyType::LITERAL)),
222  frozenPointsZone_(dict.getOrDefault("frozenPointsZone", word::null))
223 {
224  read(this->patch().boundaryMesh().mesh().time(), dict);
225 }
226 
227 
230 (
232  const pointPatch& p,
234  const pointPatchFieldMapper&
235 )
236 :
238  velocity_(ppf.velocity_),
239  featFileName_(ppf.featFileName_),
240  frozenPointsZone_(ppf.frozenPointsZone_)
241 {}
242 
243 
246 (
248 )
249 :
251  velocity_(ppf.velocity_),
252  featFileName_(ppf.featFileName_),
253  frozenPointsZone_(ppf.frozenPointsZone_)
254 {}
255 
256 
259 (
262 )
263 :
264  pointPatchVectorField(ppf, iF),
265  velocity_(ppf.velocity_),
266  featFileName_(ppf.featFileName_),
267  frozenPointsZone_(ppf.frozenPointsZone_)
268 {}
270 
271 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
272 
275 {
276  if (!edgeTreePtr_)
277  {
278  const Time& tm = this->patch().boundaryMesh().mesh().time();
279  const auto& eMesh = tm.lookupObject<edgeMesh>(featFileName_);
280 
281  const pointField& points = eMesh.points();
282  const edgeList& edges = eMesh.edges();
283 
284  // Calculate bb of all points
285  treeBoundBox bb(points);
286 
287  // Random number generator. Bit dodgy since not exactly random ;-)
288  Random rndGen(65431);
289 
290  // Slightly extended bb. Slightly off-centred just so on symmetric
291  // geometry there are less face/edge aligned items.
292  bb.inflate(rndGen, 1e-4, ROOTVSMALL);
293 
294  edgeTreePtr_.reset
295  (
297  (
298  treeDataEdge(edges, points), // All edges
299 
300  bb, // overall search domain
301  8, // maxLevel
302  10, // leafsize
303  3.0 // duplicity
304  )
305  );
306  }
308  return edgeTreePtr_();
309 }
310 
311 
313 {
314  if (this->updated())
315  {
316  return;
317  }
318 
319  const vectorField currentDisplacement(this->patchInternalField());
320 
321  // Calculate displacement to project points onto surface
322  vectorField displacement(currentDisplacement);
323  calcProjection(displacement);
324 
325 
326  // offset wrt current displacement
327  vectorField offset(displacement-currentDisplacement);
328 
329  // Clip offset to maximum displacement possible: velocity*timestep
330 
331  const Time& tm = this->patch().boundaryMesh().mesh().time();
332  const scalar deltaT = tm.deltaTValue();
333  const vector clipVelocity = velocity_*deltaT;
334 
335  forAll(displacement, i)
336  {
337  vector& d = offset[i];
338 
339  const scalar magD(mag(d));
340  if (magD > ROOTVSMALL)
341  {
342  d /= magD;
343  d *= min(magD, mag(clipVelocity));
344  }
345  }
346 
347  if (debug)
348  {
349  Pout<< type() << " :"
350  << " on patch " << patch().name()
351  << " of field " << this->internalField().name()
352  << " projection"
353  << " min:" << gMin(displacement)
354  << " max:" << gMaxMagSqr(displacement)
355  << " average:" << gAverage(displacement)
356  << endl;
357  }
358 
359  // Get internal field to insert values into
360  Field<vector>& iF = const_cast<Field<vector>&>(this->primitiveField());
361 
362  setInInternalField(iF, (currentDisplacement+offset)());
363 
365 }
366 
367 
369 (
370  Ostream& os
371 ) const
372 {
374  os.writeEntry("file", featFileName_);
376  (
377  "frozenPointsZone",
378  word::null,
379  frozenPointsZone_
380  );
381  os.writeEntry("velocity", velocity_);
382 }
383 
384 
385 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
386 
387 namespace Foam
388 {
389 
391 (
393  edgeSlipDisplacementPointPatchVectorField
394 );
395 
396 } // End namespace Foam
397 
398 // ************************************************************************* //
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
A class for handling keywords in dictionaries.
Definition: keyType.H:66
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
const Type & lookupObject(const word &name, const bool recursive=false) const
Lookup and return const reference to the object of the given Type. Fatal if not found or the wrong ty...
A class for handling file names.
Definition: fileName.H:72
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
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 inflate(const scalar factor)
Expand box by factor*mag(span) in all dimensions.
Definition: boundBoxI.H:381
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Random rndGen
Definition: createFields.H:23
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface...
Definition: boundaryMesh.H:58
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
Holds data for octree to work on an edges subset.
Definition: treeDataEdge.H:53
virtual void write(Ostream &os) const
Write.
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:321
Ignore writing from objectRegistry::writeObject()
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
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)
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1063
#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
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
const pointField & points
A class for handling words, derived from Foam::string.
Definition: word.H:63
const Time & time() const noexcept
Return time registry.
scalar mag() const
The magnitude/length of the bounding box diagonal.
Definition: boundBoxI.H:198
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
Tree tree(triangles.begin(), triangles.end())
edgeSlipDisplacementPointPatchVectorField(const pointPatch &, const DimensionedField< vector, pointMesh > &)
Construct from patch and internal field.
static const word null
An empty word.
Definition: word.H:84
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.
static bool canRead(const fileName &name, bool verbose=false)
Can we read this file format?
Vector< scalar > vector
Definition: vector.H:57
String literal.
Definition: keyType.H:82
label whichPoint(const label globalPointID) const
Helper function to re-direct to zone::localID(...)
Definition: pointZone.C:156
static void read(const objectRegistry &obr, const dictionary &dict)
Read (& store) geometry. Exposed so point attraction can reuse it.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
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
Random number generator.
Definition: Random.H:55
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:112
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)
Mesh data needed to do the Finite Area discretisation.
Definition: edgeFaMesh.H:47
pointPatchField< vector > pointPatchVectorField
const pointZoneMesh & pointZones() const noexcept
Return point zone mesh.
Definition: polyMesh.H:663
pointField points0(pointIOField(IOobject("points", mesh.time().constant(), polyMesh::meshSubDir, mesh, IOobject::MUST_READ, IOobject::NO_WRITE, IOobject::NO_REGISTER)))
A subset of mesh points.
Definition: pointZone.H:61
vector point
Point is a vector.
Definition: point.H:37
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:629
Basic pointPatch represents a set of points from the mesh.
Definition: pointPatch.H:64
const word & name() const noexcept
The zone name.
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.
Standard boundBox with extra functionality for use in octree.
Definition: treeBoundBox.H:90
messageStream Info
Information stream (stdout output on master, null elsewhere)
makePointPatchTypeField(pointPatchVectorField, solidBodyMotionDisplacementPointPatchVectorField)
const boundBox & bounds() const noexcept
Return mesh bounding box.
Definition: polyMesh.H:617
Field< vector > vectorField
Specialisation of Field<T> for vector.
bool foundObject(const word &name, const bool recursive=false) const
Is the named Type found?
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
Displacement follows an edgeMesh. Use in a displacementMotionSolver as a bc on the pointDisplacement ...
volScalarField & p
Registry of regIOobjects.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
Request registration (bool: true)
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Namespace for OpenFOAM.
IOporosityModelList pZones(mesh)
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127