searchableExtrudedCircle.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) 2016-2017 OpenFOAM Foundation
9  Copyright (C) 2019 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 "edgeMesh.H"
33 #include "indexedOctree.H"
34 #include "treeDataEdge.H"
36 #include "quaternion.H"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(searchableExtrudedCircle, 0);
44  (
45  searchableSurface,
46  searchableExtrudedCircle,
47  dict
48  );
50  (
51  searchableSurface,
52  searchableExtrudedCircle,
53  dict,
54  extrudedCircle
55  );
56 }
57 
58 
59 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
60 
61 Foam::searchableExtrudedCircle::searchableExtrudedCircle
62 (
63  const IOobject& io,
64  const dictionary& dict
65 )
66 :
68  eMeshPtr_
69  (
71  (
72  IOobject
73  (
74  dict.get<word>("file"), // name
75  io.time().constant(), // instance
76  "geometry", // local
77  io.time(), // registry
78  IOobject::MUST_READ,
79  IOobject::NO_WRITE,
80  false
81  ).objectPath()
82  )
83  ),
84  radius_(dict.get<scalar>("radius"))
85 {
86  const edgeMesh& eMesh = eMeshPtr_();
87 
88  const pointField& points = eMesh.points();
89  const edgeList& edges = eMesh.edges();
90  bounds() = boundBox(points, false);
91 
92  vector halfSpan(0.5*bounds().span());
93  point ctr(bounds().centre());
94 
95  bounds().min() = ctr - mag(halfSpan) * vector::one;
96  bounds().max() = ctr + mag(halfSpan) * vector::one;
97 
98  // Calculate bb of all points
99  treeBoundBox bb(bounds());
100 
101  // Slightly extended bb. Slightly off-centred just so on symmetric
102  // geometry there are less face/edge aligned items.
103  bb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
104  bb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
105 
106  edgeTree_.reset
107  (
109  (
111  (
112  false, // do not cache bb
113  edges,
114  points,
115  identity(edges.size())
116  ),
117  bb, // overall search domain
118  8, // maxLevel
119  10, // leafsize
120  3.0 // duplicity
121  )
122  );
123 }
124 
125 
126 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
127 
129 {}
130 
131 
132 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
133 
135 {
136  if (regions_.empty())
137  {
138  regions_.setSize(1);
139  regions_[0] = "region0";
140  }
141  return regions_;
142 }
143 
144 
146 {
147  return eMeshPtr_().points().size();
148 }
149 
150 
152 {
153  return eMeshPtr_().points();
154 }
155 
156 
158 (
159  pointField& centres,
160  scalarField& radiusSqr
161 ) const
162 {
163  centres = eMeshPtr_().points();
164  radiusSqr.setSize(centres.size());
165  radiusSqr = Foam::sqr(radius_);
166  // Add a bit to make sure all points are tested inside
167  radiusSqr += Foam::sqr(SMALL);
168 }
169 
170 
172 (
173  const pointField& samples,
174  const scalarField& nearestDistSqr,
175  List<pointIndexHit>& info
176 ) const
177 {
178  const indexedOctree<treeDataEdge>& tree = edgeTree_();
179 
180  info.setSize(samples.size());
181 
182  forAll(samples, i)
183  {
184  info[i] = tree.findNearest(samples[i], nearestDistSqr[i]);
185 
186  if (info[i].hit())
187  {
188  const vector d = normalised(samples[i] - info[i].hitPoint());
189 
190  info[i].setPoint(info[i].hitPoint() + d*radius_);
191  }
192  }
193 }
194 
195 
197 (
198  const point& start,
199  const point& end,
200  const scalarField& rawLambdas,
201  const scalarField& nearestDistSqr,
202  List<pointIndexHit>& info
203 ) const
204 {
205  const edgeMesh& mesh = eMeshPtr_();
206  const indexedOctree<treeDataEdge>& tree = edgeTree_();
207  const edgeList& edges = mesh.edges();
208  const pointField& points = mesh.points();
209  const labelListList& pointEdges = mesh.pointEdges();
210 
211  const scalar maxDistSqr(Foam::magSqr(bounds().span()));
212 
213  // Normalise lambdas
214  const scalarField lambdas
215  (
216  (rawLambdas-rawLambdas[0])
217  /(rawLambdas.last()-rawLambdas[0])
218  );
219 
220 
221  // Nearest point on curve and local axis direction
222  pointField curvePoints(lambdas.size());
223  vectorField axialVecs(lambdas.size());
224 
225  const pointIndexHit startInfo = tree.findNearest(start, maxDistSqr);
226  curvePoints[0] = startInfo.hitPoint();
227  axialVecs[0] = edges[startInfo.index()].vec(points);
228 
229  const pointIndexHit endInfo = tree.findNearest(end, maxDistSqr);
230  curvePoints.last() = endInfo.hitPoint();
231  axialVecs.last() = edges[endInfo.index()].vec(points);
232 
233 
234 
235  scalarField curveLambdas(points.size(), -1.0);
236 
237  {
238  scalar endDistance = -1.0;
239 
240  // Determine edge lengths walking from start to end.
241 
242  const point& start = curvePoints[0];
243  const point& end = curvePoints.last();
244 
245  label edgei = startInfo.index();
246  const edge& startE = edges[edgei];
247 
248  label pointi = startE[0];
249  if ((startE.vec(points)&(end-start)) > 0)
250  {
251  pointi = startE[1];
252  }
253 
254  curveLambdas[pointi] = mag(points[pointi]-curvePoints[0]);
255  label otherPointi = startE.otherVertex(pointi);
256  curveLambdas[otherPointi] = -mag(points[otherPointi]-curvePoints[0]);
257 
258  //Pout<< "for point:" << points[pointi] << " have distance "
259  // << curveLambdas[pointi] << endl;
260 
261 
262  while (true)
263  {
264  const labelList& pEdges = pointEdges[pointi];
265  if (pEdges.size() == 1)
266  {
267  break;
268  }
269  else if (pEdges.size() != 2)
270  {
271  FatalErrorInFunction << "Curve " << name()
272  << " is not a single path. This is not supported"
273  << exit(FatalError);
274  break;
275  }
276 
277  label oldEdgei = edgei;
278  if (pEdges[0] == oldEdgei)
279  {
280  edgei = pEdges[1];
281  }
282  else
283  {
284  edgei = pEdges[0];
285  }
286 
287  if (edgei == endInfo.index())
288  {
289  endDistance = curveLambdas[pointi] + mag(end-points[pointi]);
290 
291  //Pout<< "Found end edge:" << edges[edgei].centre(points)
292  // << " endPt:" << end
293  // << " point before:" << points[pointi]
294  // << " accumulated length:" << endDistance << endl;
295  }
296 
297 
298  label oldPointi = pointi;
299  pointi = edges[edgei].otherVertex(oldPointi);
300 
301  if (curveLambdas[pointi] >= 0)
302  {
303  break;
304  }
305 
306  curveLambdas[pointi] =
307  curveLambdas[oldPointi] + edges[edgei].mag(points);
308  }
309 
310  // Normalise curveLambdas
311  forAll(curveLambdas, i)
312  {
313  if (curveLambdas[i] >= 0)
314  {
315  curveLambdas[i] /= endDistance;
316  }
317  }
318  }
319 
320 
321 
322  // Interpolation engine
323  linearInterpolationWeights interpolator(curveLambdas);
324 
325  // Find wanted location along curve
326  labelList indices;
327  scalarField weights;
328  for (label i = 1; i < curvePoints.size()-1; i++)
329  {
330  interpolator.valueWeights(lambdas[i], indices, weights);
331 
332  if (indices.size() == 1)
333  {
334  // On outside of curve. Choose one of the connected edges.
335  label pointi = indices[0];
336  const point& p0 = points[pointi];
337  label edge0 = pointEdges[pointi][0];
338  const edge& e0 = edges[edge0];
339  axialVecs[i] = e0.vec(points);
340  curvePoints[i] = weights[0]*p0;
341  }
342  else if (indices.size() == 2)
343  {
344  const point& p0 = points[indices[0]];
345  const point& p1 = points[indices[1]];
346  axialVecs[i] = p1-p0;
347  curvePoints[i] = weights[0]*p0+weights[1]*p1;
348  }
349  }
350  axialVecs /= mag(axialVecs);
351 
352 
353  // Now we have the lambdas, curvePoints and axialVecs.
354 
355 
356 
357  info.setSize(lambdas.size());
358  info = pointIndexHit();
359 
360  // Given the current lambdas interpolate radial direction inbetween
361  // endpoints (all projected onto the starting coordinate system)
362  quaternion qStart;
363  vector radialStart;
364  {
365  radialStart = start-curvePoints[0];
366  radialStart -= (radialStart&axialVecs[0])*axialVecs[0];
367  radialStart.normalise();
368 
369  qStart = quaternion(radialStart, 0.0);
370 
371  info[0] = pointIndexHit(true, start, 0);
372  }
373 
374  quaternion qProjectedEnd;
375  {
376  vector radialEnd(end-curvePoints.last());
377  radialEnd -= (radialEnd&axialVecs.last())*axialVecs.last();
378  radialEnd.normalise();
379 
380  vector projectedEnd = radialEnd;
381  projectedEnd -= (projectedEnd&axialVecs[0])*axialVecs[0];
382  projectedEnd.normalise();
383 
384  qProjectedEnd = quaternion(projectedEnd, 0.0);
385 
386  info.last() = pointIndexHit(true, end, 0);
387  }
388 
389  for (label i = 1; i < lambdas.size()-1; i++)
390  {
391  quaternion q(slerp(qStart, qProjectedEnd, lambdas[i]));
392  vector radialDir(q.transform(radialStart));
393 
394  radialDir -= (radialDir & axialVecs[i]) * axialVecs.last();
395  radialDir.normalise();
396 
397  info[i] = pointIndexHit(true, curvePoints[i]+radius_*radialDir, 0);
398  }
399 }
400 
401 
403 (
404  const List<pointIndexHit>& info,
405  labelList& region
406 ) const
407 {
408  region.setSize(info.size());
409  region = 0;
410 }
411 
412 
414 (
415  const List<pointIndexHit>& info,
416  vectorField& normal
417 ) const
418 {
419  const edgeMesh& mesh = eMeshPtr_();
420  const indexedOctree<treeDataEdge>& tree = edgeTree_();
421  const edgeList& edges = mesh.edges();
422  const pointField& points = mesh.points();
423 
424  normal.setSize(info.size());
425  normal = Zero;
426 
427  forAll(info, i)
428  {
429  if (info[i].hit())
430  {
431  // Find nearest on curve
432  pointIndexHit curvePt = tree.findNearest
433  (
434  info[i].hitPoint(),
435  Foam::magSqr(bounds().span())
436  );
437 
438  normal[i] = info[i].hitPoint()-curvePt.hitPoint();
439 
440  // Subtract axial direction
441  const vector axialVec = edges[curvePt.index()].unitVec(points);
442 
443  normal[i] -= (normal[i] & axialVec) * axialVec;
444  normal[i].normalise();
445  }
446  }
447 }
448 
449 
450 // ************************************************************************* //
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
searchableExtrudedCircle.H
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1038
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:104
Foam::searchableExtrudedCircle::coordinates
virtual tmp< pointField > coordinates() const
Get representative set of element coordinates.
Definition: searchableExtrudedCircle.C:151
Foam::PointIndexHit::index
label index() const
Return index.
Definition: PointIndexHit.H:113
Foam::searchableExtrudedCircle::findParametricNearest
virtual void findParametricNearest(const point &start, const point &end, const scalarField &lambdas, const scalarField &nearestDistSqr, List< pointIndexHit > &) const
Unique to parametric geometry: given points find.
Definition: searchableExtrudedCircle.C:197
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::searchableExtrudedCircle::findNearest
virtual void findNearest(const pointField &sample, const scalarField &nearestDistSqr, List< pointIndexHit > &) const
Definition: searchableExtrudedCircle.C:172
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::slerp
quaternion slerp(const quaternion &qa, const quaternion &qb, const scalar t)
Spherical linear interpolation of quaternions.
Definition: quaternion.C:78
quaternion.H
Foam::searchableExtrudedCircle::getNormal
virtual void getNormal(const List< pointIndexHit > &, vectorField &normal) const
From a set of points and indices get the normal.
Definition: searchableExtrudedCircle.C:414
Foam::treeBoundBox
Standard boundBox with extra functionality for use in octree.
Definition: treeBoundBox.H:87
indexedOctree.H
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:63
Foam::boundBox::max
const point & max() const
Maximum describing the bounding box.
Definition: boundBoxI.H:97
Foam::primitiveMesh::edges
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
Definition: primitiveMeshEdges.C:505
Foam::primitiveMesh::pointEdges
const labelListList & pointEdges() const
Definition: primitiveMeshEdges.C:516
Foam::Vector::normalise
Vector< Cmpt > & normalise()
Normalise the vector by its magnitude.
Definition: VectorI.H:128
Foam::IOobject::time
const Time & time() const
Return time.
Definition: IOobject.C:438
Foam::boundBox::min
const point & min() const
Minimum describing the bounding box.
Definition: boundBoxI.H:91
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::quaternion
Quaternion class used to perform rotations in 3D space.
Definition: quaternion.H:56
Foam::searchableExtrudedCircle::regions
virtual const wordList & regions() const
Names of regions.
Definition: searchableExtrudedCircle.C:134
Foam::searchableExtrudedCircle::~searchableExtrudedCircle
virtual ~searchableExtrudedCircle()
Destructor.
Definition: searchableExtrudedCircle.C:128
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
linearInterpolationWeights.H
Foam::PointIndexHit
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
Definition: PointIndexHit.H:55
Foam::label
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:62
Foam::Field< vector >
edgeMesh.H
Foam::PointIndexHit::hitPoint
const Point & hitPoint() const
Return hit point.
Definition: PointIndexHit.H:119
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::searchableSurface
Base class of (analytical or triangulated) surface. Encapsulates all the search routines....
Definition: searchableSurface.H:69
Foam::edgeMesh::points
const pointField & points() const
Return points.
Definition: edgeMeshI.H:99
Foam::addNamedToRunTimeSelectionTable
addNamedToRunTimeSelectionTable(topoSetCellSource, badQualityToCell, word, badQuality)
Foam::indexedOctree
Non-pointer based hierarchical recursive searching.
Definition: treeDataEdge.H:50
Foam::searchableExtrudedCircle::getRegion
virtual void getRegion(const List< pointIndexHit > &, labelList &region) const
From a set of points and indices get the region.
Definition: searchableExtrudedCircle.C:403
Foam::treeDataEdge
Holds data for octree to work on an edges subset.
Definition: treeDataEdge.H:56
samples
scalarField samples(nIntervals, Zero)
Foam::edgeMesh::edges
const edgeList & edges() const
Return edges.
Definition: edgeMeshI.H:105
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::linearInterpolationWeights::valueWeights
virtual bool valueWeights(const scalar t, labelList &indices, scalarField &weights) const
Calculate weights and indices to calculate t from samples.
Definition: linearInterpolationWeights.C:89
Foam::linearInterpolationWeights
Definition: linearInterpolationWeights.H:50
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
stdFoam::end
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:115
treeDataEdge.H
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::searchableExtrudedCircle::boundingSpheres
virtual void boundingSpheres(pointField &centres, scalarField &radiusSqr) const
Get bounding spheres (centre and radius squared), one per element.
Definition: searchableExtrudedCircle.C:158
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::edge::otherVertex
label otherVertex(const label pointLabel) const
Given the point label for one vertex, return the other one.
Definition: edgeI.H:178
Foam::normalised
VectorSpace< Form, Cmpt, Ncmpts > normalised(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:496
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
Time.H
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::pointIndexHit
PointIndexHit< point > pointIndexHit
Definition: pointIndexHit.H:45
Foam::edge::vec
vector vec(const UList< point > &pts) const
Return the vector (end - start)
Definition: edgeI.H:407
Foam::Vector< scalar >
Foam::List< edge >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::start
label ListType::const_reference const label start
Definition: ListOps.H:408
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
p0
const volScalarField & p0
Definition: EEqn.H:36
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::TimePaths::constant
const word & constant() const
Return constant name.
Definition: TimePathsI.H:88
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::edgeMesh
Mesh data needed to do the Finite Area discretisation.
Definition: edgeFaMesh.H:52
Foam::searchableExtrudedCircle::size
virtual label size() const
Range of local indices that can be returned.
Definition: searchableExtrudedCircle.C:145
Foam::quaternion::transform
vector transform(const vector &v) const
Rotate the given vector.
Definition: quaternionI.H:331