Loading...
Searching...
No Matches
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-2022 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"
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
74Foam::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
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];
127 }
128}
129
130
131// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
132
133Foam::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 if (debugStr)
234 {
235 debugStr().writeLine(points[i], hits[i].point());
236 }
237 points[i] = hits[i].point();
238 }
239 }
240 }
241
242 if (debug)
243 {
244 Pout<< "Iter:" << iter << " initialResidual:" << initialResidual
245 << " iResidual+jResidual:" << iResidual+jResidual << endl;
246 }
247
248
249 if
250 (
251 iter > 0
252 && (
253 initialResidual < ROOTVSMALL
254 || ((iResidual+jResidual)/initialResidual < relTol)
255 )
256 )
257 {
258 break;
259 }
260
261
262 // Predict along i
263 vectorField residual(points.size(), Zero);
264
265 // Work arrays for interpolation
266 labelList indices;
267 scalarField weights;
268 for (label j = 1; j < n.second()-1; j++)
269 {
270 // Calculate actual lamdba along constant j line
271 scalarField projLambdas(n.first());
272 projLambdas[0] = 0.0;
273 for (label i = 1; i < n.first(); i++)
274 {
275 label ij = index(n, labelPair(i, j));
276 label iMin1j = index(n, labelPair(i-1, j));
277 projLambdas[i] =
278 projLambdas[i-1]
279 +mag(points[ij]-points[iMin1j]);
280 }
281 projLambdas /= projLambdas.last();
282
283 linearInterpolationWeights interpolator(projLambdas);
284
285 for (label i = 1; i < n.first()-1; i++)
286 {
287 label ij = index(n, labelPair(i, j));
288
289 interpolator.valueWeights(lambdaI[ij], indices, weights);
290
291 point predicted(Zero);
292 forAll(indices, indexi)
293 {
294 label ptIndex = index(n, labelPair(indices[indexi], j));
295 predicted += weights[indexi]*points[ptIndex];
296 }
297 residual[ij] = predicted-points[ij];
298 }
299 }
300
301 if (debugStr)
302 {
303 forAll(points, i)
304 {
305 const point predicted(points[i] + residual[i]);
306 debugStr().writeLine(points[i], predicted);
307 }
308 }
309
310 iResidual = sum(mag(residual));
311
312 // Update points before doing j. Note: is this needed? Complicates
313 // residual checking.
314 points += residual;
315
316
317 // Predict along j
318 residual = vector::zero;
319 for (label i = 1; i < n.first()-1; i++)
320 {
321 // Calculate actual lamdba along constant i line
322 scalarField projLambdas(n.second());
323 projLambdas[0] = 0.0;
324 for (label j = 1; j < n.second(); j++)
325 {
326 label ij = index(n, labelPair(i, j));
327 label ijMin1 = index(n, labelPair(i, j-1));
328 projLambdas[j] =
329 projLambdas[j-1]
330 +mag(points[ij]-points[ijMin1]);
331 }
332
333 projLambdas /= projLambdas.last();
334
335 linearInterpolationWeights interpolator(projLambdas);
336
337 for (label j = 1; j < n.second()-1; j++)
338 {
339 label ij = index(n, labelPair(i, j));
340
341 interpolator.valueWeights(lambdaJ[ij], indices, weights);
342
343 point predicted(Zero);
344 forAll(indices, indexi)
345 {
346 label ptIndex = index(n, labelPair(i, indices[indexi]));
347 predicted += weights[indexi]*points[ptIndex];
348 }
349 residual[ij] = predicted-points[ij];
350 }
351 }
352
353 if (debugStr)
354 {
355 forAll(points, i)
356 {
357 const point predicted(points[i] + residual[i]);
358 debugStr().writeLine(points[i], predicted);
359 }
360 }
361
362 jResidual = sum(mag(residual));
363
364 if (iter == 0)
365 {
366 initialResidual = iResidual + jResidual;
367 }
368
369 points += residual;
370 }
371}
372
373
374// ************************************************************************* //
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:60
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
An OFstream that keeps track of vertices and provides convenience output methods for OBJ files.
Definition OBJstream.H:58
T & last()
Access last element of the list, position [size()-1].
Definition UList.H:971
static const Form zero
const Cmpt & x() const noexcept
Access to the vector x component.
Definition Vector.H:135
const Cmpt & z() const noexcept
Access to the vector z component.
Definition Vector.H:145
const Cmpt & y() const noexcept
Access to the vector y component.
Definition Vector.H:140
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition autoPtrI.H:37
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:54
blockFace(const face &vertices)
Construct from face vertices.
Definition blockFace.C:37
Projects the given set of face points onto the selected surface of the geometry provided as a searcha...
Definition projectFace.H:53
virtual void project(const blockDescriptor &, const label blockFacei, pointField &points) const
Project the given points onto the surface.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
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,...
A class for handling words, derived from Foam::string.
Definition word.H:66
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
auto & name
const pointField & points
Namespace for handling debugging switches.
Definition debug.C:45
Namespace for OpenFOAM.
Pair< label > labelPair
A pair of labels.
Definition Pair.H:54
List< label > labelList
A List of labels.
Definition List.H:62
messageStream Info
Information stream (stdout output on master, null elsewhere).
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Field< vector > vectorField
Specialisation of Field<T> for vector.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
vector point
Point is a vector.
Definition point.H:37
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &f1, const label comm)
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
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:299
Unit conversion functions.