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-2020 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
29#include "projectFace.H"
30#include "unitConversion.H"
32#include "blockDescriptor.H"
33#include "OBJstream.H"
35
36// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37
38namespace Foam
39{
40namespace blockFaces
41{
44}
45}
46
47
48// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49
50const 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"
69
70 return geometry[0];
71}
72
73
75(
76 const labelPair& n,
77 const labelPair& coord
78)
79{
80 return coord.first() + coord.second()*n.first();
81}
82
83
84void 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
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 {
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)
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
251 (
252 iter > 0
253 && (
254 initialResidual < ROOTVSMALL
255 || ((iResidual+jResidual)/initialResidual < relTol)
256 )
257 )
258 {
259 break;
260 }
261
262
263 // Predict along i
264 vectorField residual(points.size(), Zero);
265
266 // Work arrays for interpolation
267 labelList indices;
268 scalarField weights;
269 for (label j = 1; j < n.second()-1; j++)
270 {
271 // Calculate actual lamdba along constant j line
272 scalarField projLambdas(n.first());
273 projLambdas[0] = 0.0;
274 for (label i = 1; i < n.first(); i++)
275 {
276 label ij = index(n, labelPair(i, j));
277 label iMin1j = index(n, labelPair(i-1, j));
278 projLambdas[i] =
279 projLambdas[i-1]
280 +mag(points[ij]-points[iMin1j]);
281 }
282 projLambdas /= projLambdas.last();
283
284 linearInterpolationWeights interpolator(projLambdas);
285
286 for (label i = 1; i < n.first()-1; i++)
287 {
288 label ij = index(n, labelPair(i, j));
289
290 interpolator.valueWeights(lambdaI[ij], indices, weights);
291
292 point predicted(Zero);
293 forAll(indices, indexi)
294 {
295 label ptIndex = index(n, labelPair(indices[indexi], j));
296 predicted += weights[indexi]*points[ptIndex];
297 }
298 residual[ij] = predicted-points[ij];
299 }
300 }
301
302 if (debugStr)
303 {
304 forAll(points, i)
305 {
306 const point predicted(points[i] + residual[i]);
307 debugStr().write(linePointRef(points[i], predicted));
308 }
309 }
310
311 iResidual = sum(mag(residual));
312
313 // Update points before doing j. Note: is this needed? Complicates
314 // residual checking.
315 points += residual;
316
317
318 // Predict along j
319 residual = vector::zero;
320 for (label i = 1; i < n.first()-1; i++)
321 {
322 // Calculate actual lamdba along constant i line
323 scalarField projLambdas(n.second());
324 projLambdas[0] = 0.0;
325 for (label j = 1; j < n.second(); j++)
326 {
327 label ij = index(n, labelPair(i, j));
328 label ijMin1 = index(n, labelPair(i, j-1));
329 projLambdas[j] =
330 projLambdas[j-1]
331 +mag(points[ij]-points[ijMin1]);
332 }
333
334 projLambdas /= projLambdas.last();
335
336 linearInterpolationWeights interpolator(projLambdas);
337
338 for (label j = 1; j < n.second()-1; j++)
339 {
340 label ij = index(n, labelPair(i, j));
341
342 interpolator.valueWeights(lambdaJ[ij], indices, weights);
343
344 point predicted(Zero);
345 forAll(indices, indexi)
346 {
347 label ptIndex = index(n, labelPair(i, indices[indexi]));
348 predicted += weights[indexi]*points[ptIndex];
349 }
350 residual[ij] = predicted-points[ij];
351 }
352 }
353
354 if (debugStr)
355 {
356 forAll(points, i)
357 {
358 const point predicted(points[i] + residual[i]);
359 debugStr().write(linePointRef(points[i], predicted));
360 }
361 }
362
363 jResidual = sum(mag(residual));
364
365 if (iter == 0)
366 {
367 initialResidual = iResidual + jResidual;
368 }
369
370 points += residual;
371 }
372}
373
374
375// ************************************************************************* //
label n
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:64
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
OFstream that keeps track of vertices.
Definition: OBJstream.H:61
T & last()
Return the last element of the list.
Definition: UListI.H:216
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:85
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:79
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:73
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
void reset(autoPtr< T > &&other) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:117
Takes the description of the block and the list of curved edges and creates a list of points on edges...
const pointField & vertices() const noexcept
Reference to point field defining the block mesh.
const cellShape & blockShape() const noexcept
Return the block shape.
const labelVector & density() const noexcept
The mesh density (number of cells) in the i,j,k directions.
Define a curved face.
Definition: blockFace.H:58
Projects the given set of face points onto the selected surface of the geometry provided as a searcha...
Definition: projectFace.H:57
virtual void project(const blockDescriptor &, const label blockFacei, pointField &points) const
Project the given points onto the surface.
Definition: projectFace.C:149
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
virtual bool valueWeights(const scalar t, labelList &indices, scalarField &weights) const
Calculate weights and indices to calculate t from samples.
Base class of (analytical or triangulated) surface. Encapsulates all the search routines....
Container for searchableSurfaces. The collection is specified as a dictionary. For example,...
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
const pointField & points
Namespace for OpenFOAM.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:57
line< point, const point & > linePointRef
A line using referred points.
Definition: linePointRef.H:47
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
messageStream Info
Information stream (stdout output on master, null elsewhere)
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
IOerror FatalIOError
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
A non-counting (dummy) refCount.
Definition: refCount.H:59
Unit conversion functions.