Loading...
Searching...
No Matches
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-2025 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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
39const Foam::Enum
40<
42>
43Foam::surfaceSlipDisplacementPointPatchVectorField::projectModeNames_
44({
45 { projectMode::NEAREST, "nearest" },
46 { projectMode::POINTNORMAL, "pointNormal" },
47 { projectMode::FIXEDNORMAL, "fixedNormal" },
48});
49
50
51// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52
53void 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 = mesh.pointZones().cfindZone(frozenPointsZone_);
80
81 if (zonePtr)
82 {
83 Pout<< "surfaceSlipDisplacementPointPatchVectorField : Fixing all "
84 << zonePtr->size() << " points in pointZone " << zonePtr->name()
85 << endl;
86 }
87 else if (!frozenPointsZone_.empty())
88 {
90 << "Cannot find frozen point zone: " << frozenPointsZone_ << nl
91 << exit(FatalError);
92 }
93
94 // Get the starting locations from the motionSolver
95 const pointField& points0 = mesh.lookupObject<displacementMotionSolver>
96 (
97 "dynamicMeshDict"
98 ).points0();
99
100
101 pointField start(meshPoints.size());
102 forAll(start, i)
103 {
104 start[i] = points0[meshPoints[i]] + displacement[i];
105 }
106
107 label nNotProjected = 0;
108
109 if (projectMode_ == NEAREST)
110 {
111 List<pointIndexHit> nearest;
112 labelList hitSurfaces;
114 (
115 start,
116 scalarField(start.size(), sqr(projectLen)),
117 hitSurfaces,
118 nearest
119 );
120
121 forAll(nearest, i)
122 {
123 if (zonePtr && (zonePtr->whichPoint(meshPoints[i]) >= 0))
124 {
125 // Fixed point. Reset to point0 location.
126 displacement[i] = points0[meshPoints[i]] - localPoints[i];
127 }
128 else if (nearest[i].hit())
129 {
130 displacement[i] = nearest[i].point() - points0[meshPoints[i]];
131 }
132 else
133 {
134 nNotProjected++;
135
136 if (debug)
137 {
138 Pout<< " point:" << meshPoints[i]
139 << " coord:" << localPoints[i]
140 << " did not find any surface within " << projectLen
141 << endl;
142 }
143 }
144 }
145 }
146 else
147 {
148 // Do tests on all points. Combine later on.
149
150 // 1. Check if already on surface
151 List<pointIndexHit> nearest;
152 {
153 labelList nearestSurface;
155 (
156 start,
157 scalarField(start.size(), sqr(SMALL)),
158 nearestSurface,
159 nearest
160 );
161 }
162
163 // 2. intersection. (combined later on with information from nearest
164 // above)
165 vectorField projectVecs(start.size(), projectVec);
166
167 if (projectMode_ == POINTNORMAL)
168 {
169 projectVecs = projectLen*patch().pointNormals();
170 }
171
172 // Knock out any wedge component
173 scalarField offset(start.size(), Zero);
174 if (wedgePlane_ >= 0 && wedgePlane_ < vector::nComponents)
175 {
176 forAll(offset, i)
177 {
178 offset[i] = start[i][wedgePlane_];
179 start[i][wedgePlane_] = 0;
180 projectVecs[i][wedgePlane_] = 0;
181 }
182 }
183
184 List<pointIndexHit> rightHit;
185 {
186 labelList rightSurf;
188 (
189 start,
190 start+projectVecs,
191 rightSurf,
192 rightHit
193 );
194 }
195
196 List<pointIndexHit> leftHit;
197 {
198 labelList leftSurf;
200 (
201 start,
202 start-projectVecs,
203 leftSurf,
204 leftHit
205 );
206 }
207
208 // 3. Choose either -fixed, nearest, right, left.
209 forAll(displacement, i)
210 {
211 if (zonePtr && (zonePtr->whichPoint(meshPoints[i]) >= 0))
212 {
213 // Fixed point. Reset to point0 location.
214 displacement[i] = points0[meshPoints[i]] - localPoints[i];
215 }
216 else if (nearest[i].hit())
217 {
218 // Found nearest.
219 displacement[i] = nearest[i].point() - points0[meshPoints[i]];
220 }
221 else
222 {
223 pointIndexHit interPt;
224
225 if (rightHit[i].hit())
226 {
227 if
228 (
229 !leftHit[i].hit()
230 ||
231 (
232 start[i].distSqr(rightHit[i].point())
233 < start[i].distSqr(leftHit[i].point())
234 )
235 )
236 {
237 interPt = rightHit[i];
238 }
239 else
240 {
241 interPt = leftHit[i];
242 }
243 }
244 else
245 {
246 if (leftHit[i].hit())
247 {
248 interPt = leftHit[i];
249 }
250 }
251
252
253 if (interPt.hit())
254 {
255 if (wedgePlane_ >= 0 && wedgePlane_ < vector::nComponents)
256 {
257 interPt.point()[wedgePlane_] += offset[i];
258 }
259 displacement[i] = interPt.point() - points0[meshPoints[i]];
260 }
261 else
262 {
263 nNotProjected++;
264
265 if (debug)
266 {
267 Pout<< " point:" << meshPoints[i]
268 << " coord:" << localPoints[i]
269 << " did not find any intersection between"
270 << " ray from " << start[i]-projectVecs[i]
271 << " to " << start[i]+projectVecs[i] << endl;
272 }
273 }
274 }
275 }
276 }
277
278 if (scalePtr_)
279 {
280 const scalarField s
281 (
282 scalePtr_->value(this->db().time().timeOutputValue())
283 );
284
285 displacement *= s;
286 }
287
288 reduce(nNotProjected, sumOp<label>());
289
290 if (nNotProjected > 0)
291 {
292 Info<< "surfaceSlipDisplacement :"
293 << " on patch " << patch().name()
294 << " did not project " << nNotProjected
295 << " out of " << returnReduce(localPoints.size(), sumOp<label>())
296 << " points." << endl;
297 }
299
300
301// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
302
305(
306 const pointPatch& p,
308)
309:
311 projectMode_(NEAREST),
312 projectDir_(Zero),
313 wedgePlane_(-1)
314{}
315
316
319(
320 const pointPatch& p,
322 const dictionary& dict
323)
324:
326 surfacesDict_(dict.subDict("geometry")),
327 projectMode_(projectModeNames_.get("projectMode", dict)),
328 projectDir_
329 (
330 (projectMode_ == FIXEDNORMAL)
331 ? dict.get<vector>("projectDirection")
332 : Zero
333 ),
334 wedgePlane_(dict.getOrDefault("wedgePlane", -1)),
335 frozenPointsZone_(dict.getOrDefault("frozenPointsZone", word::null)),
336 scalePtr_(nullptr)
337{
338 if (const auto* fpp = isA<facePointPatch>(this->patch()))
339 {
340 scalePtr_ =
342 (
343 fpp->patch(),
344 "scale",
345 dict,
346 false // point values (faceValues = false)
347 );
348 }
349}
350
351
354(
355 const surfaceSlipDisplacementPointPatchVectorField& ppf,
356 const pointPatch& p,
357 const DimensionedField<vector, pointMesh>& iF,
358 const pointPatchFieldMapper&
359)
360:
362 surfacesDict_(ppf.surfacesDict_),
363 projectMode_(ppf.projectMode_),
364 projectDir_(ppf.projectDir_),
365 wedgePlane_(ppf.wedgePlane_),
366 frozenPointsZone_(ppf.frozenPointsZone_),
367 scalePtr_(nullptr)
368{
369 if (const auto* fpp = isA<facePointPatch>(this->patch()))
370 {
371 scalePtr_ = ppf.scalePtr_.clone(fpp->patch());
372 }
373}
374
375
378(
379 const surfaceSlipDisplacementPointPatchVectorField& ppf,
380 const DimensionedField<vector, pointMesh>& iF
381)
382:
383 pointPatchVectorField(ppf, iF),
384 surfacesDict_(ppf.surfacesDict_),
385 projectMode_(ppf.projectMode_),
386 projectDir_(ppf.projectDir_),
387 wedgePlane_(ppf.wedgePlane_),
388 frozenPointsZone_(ppf.frozenPointsZone_),
389 scalePtr_(nullptr)
390{
391 if (const auto* fpp = isA<facePointPatch>(this->patch()))
392 {
393 scalePtr_ = ppf.scalePtr_.clone(fpp->patch());
394 }
395}
397
398// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
399
402{
403 if (!surfacesPtr_)
404 {
405 surfacesPtr_.reset
406 (
408 (
410 (
411 "abc", // dummy name
412 db().time().constant(), // directory
413 "triSurface", // instance
414 db().time(), // registry
417 ),
418 surfacesDict_,
419 true // use single region naming shortcut
420 )
421 );
422 }
424 return *surfacesPtr_;
425}
426
427
429{
430 if (this->updated())
431 {
432 return;
433 }
434
435 vectorField displacement(this->patchInternalField());
436
437 // Calculate displacement to project points onto surface
438 calcProjection(displacement);
439
440 if (debug)
441 {
442 Pout<< type() << " :"
443 << " on patch " << patch().name()
444 << " of field " << this->internalField().name()
445 << " projection"
446 << " min:" << gMin(displacement)
447 << " max:" << gMaxMagSqr(displacement)
448 << " average:" << gAverage(displacement)
449 << endl;
450 }
451
452 // Get internal field to insert values into
453 Field<vector>& iF = const_cast<Field<vector>&>(this->primitiveField());
454
455 //setInInternalField(iF, motionU);
456 setInInternalField(iF, displacement);
459}
460
461
463(
464 Ostream& os
465) const
466{
468 os.writeEntry("geometry", surfacesDict_);
469 os.writeEntry("projectMode", projectModeNames_[projectMode_]);
470 os.writeEntryIfDifferent<vector>
471 (
472 "projectDirection",
473 Zero,
474 projectDir_
475 );
476 os.writeEntryIfDifferent<label>("wedgePlane", -1, wedgePlane_);
477 os.writeEntryIfDifferent<word>
478 (
479 "frozenPointsZone",
481 frozenPointsZone_
482 );
483
484 if (scalePtr_)
485 {
486 scalePtr_->writeData(os);
487 }
488}
489
490
491// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
492
493namespace Foam
494{
495
497(
500);
501
502} // End namespace Foam
503
504// ************************************************************************* //
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...
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition Enum.H:57
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition Field.H:172
@ MUST_READ
Reading required.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
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
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
static autoPtr< PatchFunction1< Type > > NewIfPresent(const polyPatch &pp, const word &entryName, const dictionary &dict, const bool faceValues=true)
An optional selector.
static constexpr direction nComponents
Number of components in this vector space.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
const word & name() const noexcept
The patch name.
const pointMesh & mesh() const noexcept
Return the mesh reference.
const pointPatch & patch() const noexcept
Return the patch.
const objectRegistry & db() const
The associated objectRegistry.
bool updated() const noexcept
True if the boundary condition has already been updated.
Foam::pointPatchFieldMapper.
void patchInternalField(const UList< Type1 > &internalData, const labelUList &addressing, UList< Type1 > &pfld) const
void setInInternalField(Field< Type1 > &iF, const Field< Type1 > &pF, const labelUList &meshPoints) const
const Field< vector > & primitiveField() const noexcept
virtual void write(Ostream &os) const
Write.
const DimensionedField< vector, pointMesh > & internalField() const noexcept
Basic pointPatch represents a set of points from the mesh.
Definition pointPatch.H:67
virtual const labelList & meshPoints() const =0
Return mesh points.
virtual const vectorField & localPoints() const =0
Return pointField of points in patch.
const pointBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
Definition pointPatch.H:250
virtual const vectorField & pointNormals() const =0
Return point unit normals.
Container for searchableSurfaces. The collection is specified as a dictionary. For example,...
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.
Displacement follows a triSurface. Use in a displacementMotionSolver as a bc on the pointDisplacement...
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
const searchableSurfaces & surfaces() const
Surface to follow. Demand loads surfaceNames.
surfaceSlipDisplacementPointPatchVectorField(const pointPatch &, const DimensionedField< vector, pointMesh > &)
Construct from patch and internal field.
A class for handling words, derived from Foam::string.
Definition word.H:66
static const word null
An empty word.
Definition word.H:84
volScalarField & p
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
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))
Different types of constants.
Namespace for handling debugging switches.
Definition debug.C:45
Namespace for OpenFOAM.
Type gAverage(const FieldField< Field, Type > &f, const label comm)
The global arithmetic average of a FieldField.
List< label > labelList
A List of labels.
Definition List.H:62
dimensionedSymmTensor sqr(const dimensionedVector &dv)
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
messageStream Info
Information stream (stdout output on master, null elsewhere).
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
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
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.
Type gMaxMagSqr(const UList< Type > &f, const label comm)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition typeInfo.H:87
void reduce(T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce).
Field< vector > vectorField
Specialisation of Field<T> for vector.
pointPatchField< vector > pointPatchVectorField
vector point
Point is a vector.
Definition point.H:37
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
Type gMin(const FieldField< Field, Type > &f)
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
vectorField pointField
pointField is a vectorField.
Vector< scalar > vector
Definition vector.H:57
PointIndexHit< point > pointIndexHit
A PointIndexHit with a 3D point.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define makePointPatchTypeField(PatchTypeField, typePatchTypeField)
Define a concrete pointPatchField type and add to run-time tables Example, (pointPatchScalarField,...
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
Spatial transformation functions for primitive fields.
pointField points0(pointIOField(IOobject("points", mesh.time().constant(), polyMesh::meshSubDir, mesh, IOobject::MUST_READ, IOobject::NO_WRITE, IOobject::NO_REGISTER)))