projectFace.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 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 
29 #include "projectFace.H"
30 #include "unitConversion.H"
32 #include "blockDescriptor.H"
33 #include "OBJstream.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40 namespace blockFaces
41 {
44 }
45 }
46 
47 
48 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49 
50 const Foam::searchableSurface& Foam::blockFaces::projectFace::lookupSurface
51 (
52  const searchableSurfaces& geometry,
53  Istream& is
54 ) const
55 {
56  const word name(is);
57 
58  for (const searchableSurface& geom : geometry)
59  {
60  if (geom.name() == name)
61  {
62  return geom;
63  }
64  }
65 
67  << "Cannot find surface " << name << " in geometry"
68  << exit(FatalIOError);
69 
70  return geometry[0];
71 }
72 
73 
74 Foam::label Foam::blockFaces::projectFace::index
75 (
76  const labelPair& n,
77  const labelPair& coord
78 )
79 {
80  return coord.first() + coord.second()*n.first();
81 }
82 
83 
84 void Foam::blockFaces::projectFace::calcLambdas
85 (
86  const labelPair& n,
87  const pointField& points,
88  scalarField& lambdaI,
89  scalarField& lambdaJ
90 ) const
91 {
92  lambdaI.setSize(points.size());
93  lambdaI = 0.0;
94  lambdaJ.setSize(points.size());
95  lambdaJ = 0.0;
96 
97  for (label i = 1; i < n.first(); i++)
98  {
99  for (label j = 1; j < n.second(); j++)
100  {
101  label ij = index(n, labelPair(i, j));
102  label iMin1j = index(n, labelPair(i-1, j));
103  lambdaI[ij] = lambdaI[iMin1j] + mag(points[ij]-points[iMin1j]);
104 
105  label ijMin1 = index(n, labelPair(i, j-1));
106  lambdaJ[ij] = lambdaJ[ijMin1] + mag(points[ij]-points[ijMin1]);
107  }
108  }
109 
110  for (label i = 1; i < n.first(); i++)
111  {
112  label ijLast = index(n, labelPair(i, n.second()-1));
113  for (label j = 1; j < n.second(); j++)
114  {
115  label ij = index(n, labelPair(i, j));
116  lambdaJ[ij] /= lambdaJ[ijLast];
117  }
118  }
119  for (label j = 1; j < n.second(); j++)
120  {
121  label iLastj = index(n, labelPair(n.first()-1, j));
122  for (label i = 1; i < n.first(); i++)
123  {
124  label ij = index(n, labelPair(i, j));
125  lambdaI[ij] /= lambdaI[iLastj];
126  }
127  }
128 }
129 
130 
131 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
132 
133 Foam::blockFaces::projectFace::projectFace
134 (
135  const dictionary& dict,
136  const label index,
137  const searchableSurfaces& geometry,
138  Istream& is
139 )
140 :
141  blockFace(dict, index, is),
142  surface_(lookupSurface(geometry, is))
143 {}
144 
145 
146 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
147 
149 (
150  const blockDescriptor& desc,
151  const label blockFacei,
153 ) const
154 {
155  // For debugging to tag the output
156  static label fIter = 0;
157 
158  autoPtr<OBJstream> debugStr;
159  if (debug)
160  {
161  debugStr.reset
162  (
163  new OBJstream("projectFace_" + Foam::name(fIter++) + ".obj")
164  );
165  Info<< "Face:" << blockFacei << " on block:" << desc.blockShape()
166  << " with verts:" << desc.vertices()
167  << " writing lines from start points"
168  << " to projected points to " << debugStr().name() << endl;
169  }
170 
171 
172  // Find out range of vertices in face
173  labelPair n(-1, -1);
174  switch (blockFacei)
175  {
176  case 0:
177  case 1:
178  {
179  n.first() = desc.density().y() + 1;
180  n.second() = desc.density().z() + 1;
181  }
182  break;
183 
184  case 2:
185  case 3:
186  {
187  n.first() = desc.density().x() + 1;
188  n.second() = desc.density().z() + 1;
189  }
190  break;
191 
192  case 4:
193  case 5:
194  {
195  n.first() = desc.density().x() + 1;
196  n.second() = desc.density().y() + 1;
197  }
198  break;
199  }
200 
201 
202  // Calculate initial normalised edge lengths (= u,v coordinates)
203  scalarField lambdaI(points.size(), Zero);
204  scalarField lambdaJ(points.size(), Zero);
205  calcLambdas(n, points, lambdaI, lambdaJ);
206 
207 
208  // Upper limit for number of iterations
209  const label maxIter = 10;
210  // Residual tolerance
211  const scalar relTol = 0.1;
212 
213  scalar initialResidual = 0.0;
214  scalar iResidual = 0.0;
215  scalar jResidual = 0.0;
216 
217  for (label iter = 0; iter < maxIter; iter++)
218  {
219  // Do projection
220  {
221  List<pointIndexHit> hits;
222  scalarField nearestDistSqr
223  (
224  points.size(),
225  magSqr(points[0] - points[points.size()-1])
226  );
227  surface_.findNearest(points, nearestDistSqr, hits);
228 
229  forAll(hits, i)
230  {
231  if (hits[i].hit())
232  {
233  const point& hitPt = hits[i].hitPoint();
234  if (debugStr.valid())
235  {
236  debugStr().write(linePointRef(points[i], hitPt));
237  }
238  points[i] = hitPt;
239  }
240  }
241  }
242 
243  if (debug)
244  {
245  Pout<< "Iter:" << iter << " initialResidual:" << initialResidual
246  << " iResidual+jResidual:" << iResidual+jResidual << endl;
247  }
248 
249 
250  if (iter > 0 && (iResidual+jResidual)/initialResidual < relTol)
251  {
252  break;
253  }
254 
255 
256  // Predict along i
257  vectorField residual(points.size(), Zero);
258 
259  // Work arrays for interpolation
260  labelList indices;
261  scalarField weights;
262  for (label j = 1; j < n.second()-1; j++)
263  {
264  // Calculate actual lamdba along constant j line
265  scalarField projLambdas(n.first());
266  projLambdas[0] = 0.0;
267  for (label i = 1; i < n.first(); i++)
268  {
269  label ij = index(n, labelPair(i, j));
270  label iMin1j = index(n, labelPair(i-1, j));
271  projLambdas[i] =
272  projLambdas[i-1]
273  +mag(points[ij]-points[iMin1j]);
274  }
275  projLambdas /= projLambdas.last();
276 
277  linearInterpolationWeights interpolator(projLambdas);
278 
279  for (label i = 1; i < n.first()-1; i++)
280  {
281  label ij = index(n, labelPair(i, j));
282 
283  interpolator.valueWeights(lambdaI[ij], indices, weights);
284 
285  point predicted(Zero);
286  forAll(indices, indexi)
287  {
288  label ptIndex = index(n, labelPair(indices[indexi], j));
289  predicted += weights[indexi]*points[ptIndex];
290  }
291  residual[ij] = predicted-points[ij];
292  }
293  }
294 
295  if (debugStr.valid())
296  {
297  forAll(points, i)
298  {
299  const point predicted(points[i] + residual[i]);
300  debugStr().write(linePointRef(points[i], predicted));
301  }
302  }
303 
304  iResidual = sum(mag(residual));
305 
306  // Update points before doing j. Note: is this needed? Complicates
307  // residual checking.
308  points += residual;
309 
310 
311  // Predict along j
312  residual = vector::zero;
313  for (label i = 1; i < n.first()-1; i++)
314  {
315  // Calculate actual lamdba along constant i line
316  scalarField projLambdas(n.second());
317  projLambdas[0] = 0.0;
318  for (label j = 1; j < n.second(); j++)
319  {
320  label ij = index(n, labelPair(i, j));
321  label ijMin1 = index(n, labelPair(i, j-1));
322  projLambdas[j] =
323  projLambdas[j-1]
324  +mag(points[ij]-points[ijMin1]);
325  }
326 
327  projLambdas /= projLambdas.last();
328 
329  linearInterpolationWeights interpolator(projLambdas);
330 
331  for (label j = 1; j < n.second()-1; j++)
332  {
333  label ij = index(n, labelPair(i, j));
334 
335  interpolator.valueWeights(lambdaJ[ij], indices, weights);
336 
337  point predicted(Zero);
338  forAll(indices, indexi)
339  {
340  label ptIndex = index(n, labelPair(i, indices[indexi]));
341  predicted += weights[indexi]*points[ptIndex];
342  }
343  residual[ij] = predicted-points[ij];
344  }
345  }
346 
347  if (debugStr.valid())
348  {
349  forAll(points, i)
350  {
351  const point predicted(points[i] + residual[i]);
352  debugStr().write(linePointRef(points[i], predicted));
353  }
354  }
355 
356  jResidual = sum(mag(residual));
357 
358  if (iter == 0)
359  {
360  initialResidual = iResidual + jResidual;
361  }
362 
363  points += residual;
364  }
365 }
366 
367 
368 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::autoPtr::reset
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:158
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
Foam::Vector::x
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:78
Foam::blockDescriptor::vertices
const pointField & vertices() const
Reference to point field defining the block mesh.
Definition: blockDescriptorI.H:31
Foam::OBJstream
OFstream that keeps track of vertices.
Definition: OBJstream.H:56
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::blockDescriptor::blockShape
const cellShape & blockShape() const
Return the block shape.
Definition: blockDescriptorI.H:43
unitConversion.H
Unit conversion functions.
Foam::blockFace
Define a curved face.
Definition: blockFace.H:57
Foam::autoPtr::valid
bool valid() const noexcept
True if the managed pointer is non-null.
Definition: autoPtrI.H:107
Foam::FatalIOError
IOerror FatalIOError
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
blockDescriptor.H
Foam::Vector::z
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:90
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
linearInterpolationWeights.H
Foam::labelPair
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:54
n
label n
Definition: TABSMDCalcMethod2.H:31
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::blockFaces::addToRunTimeSelectionTable
addToRunTimeSelectionTable(blockFace, projectFace, Istream)
Foam::Field< vector >
projectFace.H
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:61
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
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
dict
dictionary dict
Definition: searchingEngine.H:14
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
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::blockFaces::defineTypeNameAndDebug
defineTypeNameAndDebug(projectFace, 0)
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::blockFaces::projectFace
Projects the given set of face points onto the selected surface of the geometry provided as a searcha...
Definition: projectFace.H:54
Foam::blockFaces::projectFace::project
virtual void project(const blockDescriptor &, const label blockFacei, pointField &points) const
Project the given points onto the surface.
Definition: projectFace.C:149
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
Foam::Vector::y
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:84
Foam::linePointRef
line< point, const point & > linePointRef
Line using referred points.
Definition: linePointRef.H:47
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: Pair.H:54
Foam::Vector< scalar >
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:102
Foam::searchableSurfaces
Container for searchableSurfaces. The collection is specified as a dictionary. For example,...
Definition: searchableSurfaces.H:92
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::zero
static const Vector< scalar > zero
Definition: VectorSpace.H:115
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:375
Foam::blockDescriptor::density
const labelVector & density() const
Return the mesh density (number of cells) in the i,j,k directions.
Definition: blockDescriptorI.H:49
Foam::blockDescriptor
Takes the description of the block and the list of curved edges and creates a list of points on edges...
Definition: blockDescriptor.H:78
OBJstream.H