Loading...
Searching...
No Matches
ITHACAgeometry.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ██╗████████╗██╗ ██╗ █████╗ ██████╗ █████╗ ███████╗██╗ ██╗
3 ██║╚══██╔══╝██║ ██║██╔══██╗██╔════╝██╔══██╗ ██╔════╝██║ ██║
4 ██║ ██║ ███████║███████║██║ ███████║█████╗█████╗ ██║ ██║
5 ██║ ██║ ██╔══██║██╔══██║██║ ██╔══██║╚════╝██╔══╝ ╚██╗ ██╔╝
6 ██║ ██║ ██║ ██║██║ ██║╚██████╗██║ ██║ ██║ ╚████╔╝
7 ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═══╝
8
9 * In real Time Highly Advanced Computational Applications for Finite Volumes
10 * Copyright (C) 2017 by the ITHACA-FV authors
11-------------------------------------------------------------------------------
12License
13 This file is part of ITHACA-FV
14 ITHACA-FV is free software: you can redistribute it and/or modify
15 it under the terms of the GNU Lesser 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 ITHACA-FV is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public License
23 along with ITHACA-FV. If not, see <http://www.gnu.org/licenses/>.
24\*---------------------------------------------------------------------------*/
25#include "ITHACAgeometry.H"
26using namespace ITHACAutilities;
27
28namespace ITHACAutilities
29{
30
31labelList getIndicesFromBox(const fvMesh& mesh, List<label> indices,
32 Eigen::MatrixXd Box, List<vector>& points2Move)
33{
34 points2Move.resize(0);
35 labelList boxIndices;
36 pointField meshPoints(mesh.points());
37
38 for (label j = 0; j < indices.size(); j++)
39 {
40 const polyPatch& patchFound = mesh.boundaryMesh()[indices[j]];
41 labelList labelPatchFound(patchFound.meshPoints());
42
43 for (label i = 0; i < labelPatchFound.size(); i++)
44 {
45 auto px = meshPoints[labelPatchFound[i]].component(0);
46 auto py = meshPoints[labelPatchFound[i]].component(1);
47 auto pz = meshPoints[labelPatchFound[i]].component(2);
48
49 if (px >= min(Box(0, 0), Box(1, 0)) && py >= min(Box(0, 1), Box(1, 1))
50 && pz >= min(Box(0, 2), Box(1, 2)) && px <= max(Box(0, 0), Box(1, 0))
51 && py <= max(Box(0, 1), Box(1, 1)) && pz <= max(Box(0, 2), Box(1, 2)) )
52 {
53 boxIndices.append(labelPatchFound[i]);
54 points2Move.append(meshPoints[labelPatchFound[i]]);
55 }
56 }
57 }
58
59 return boxIndices;
60}
61
62List<label> getIndices(const fvMesh& mesh, int index, int layers)
63{
64 List<label> out;
65 out.resize(1);
66 out[0] = index;
67
68 for (label i = 0; i < layers; i++)
69 {
70 label size = out.size();
71
72 for (label j = 0; j < size; j++)
73 {
74 out.append(mesh.cellCells()[out[j]]);
75 }
76 }
77
78 labelList uniqueIndex;
79 uniqueOrder(out, uniqueIndex);
80 List<label> out2;
81 forAll(uniqueIndex, i)
82 {
83 out2.append(out[uniqueIndex[i]]);
84 }
85
86 return out2;
87}
88
89List<label> getIndices(const fvMesh& mesh, int index_row,
90 int index_col, int layers)
91{
92 List<label> out;
93 out.resize(2);
94 out[0] = index_row;
95 out[1] = index_col;
96
97 for (label i = 0; i < layers; i++)
98 {
99 label size = out.size();
100
101 for (label j = 0; j < size; j++)
102 {
103 out.append(mesh.cellCells()[out[j]]);
104 }
105 }
106
107 labelList uniqueIndex;
108 uniqueOrder(out, uniqueIndex);
109 List<label> out2;
110 forAll(uniqueIndex, i)
111 {
112 out2.append(out[uniqueIndex[i]]);
113 }
114
115 return out2;
116}
117
118void getPointsFromPatch(fvMesh& mesh, label ind,
119 List<vector>& points, labelList& indices)
120{
121 pointField meshPoints(mesh.points());
122 const polyPatch& patchFound = mesh.boundaryMesh()[ind];
123 labelList labelPatchFound(patchFound.meshPoints());
124 points.resize(labelPatchFound.size());
125
126 for (label i = 0; i < labelPatchFound.size(); i++)
127 {
128 points[i] = meshPoints[labelPatchFound[i]];
129 }
130
131 indices = labelPatchFound;
132}
133
134List<vector> displacedSegment(List<vector> x0, double mux1,
135 double mux2, double muy1, double muy2)
136{
137 vector minimum = min(x0);
138 vector maximum = max(x0);
139 double l = Foam::sqrt(pow(minimum[0] - maximum[0],
140 2) + pow(minimum[1] - maximum[1], 2));
141 double limin;
142 double limax;
143 List<vector> xdef(x0);
144 List<vector> displ(x0);
145
146 for (label i = 0; i < x0.size(); i++)
147 {
148 limin = Foam::sqrt(pow(x0[i][0] - minimum[0], 2) + pow(x0[i][1] - minimum[1],
149 2));
150 limax = Foam::sqrt(pow(x0[i][0] - maximum[0], 2) + pow(x0[i][1] - maximum[1],
151 2));
152 xdef[i][0] = x0[i][0] + mux1 * (1 - limin / l) + mux2 * (1 - limax / l);
153 xdef[i][1] = x0[i][1] + muy1 * (1 - limin / l) + muy2 * (1 - limax / l);
154 xdef[i][2] = x0[i][2];
155 }
156
157 displ = xdef - x0;
158 return displ;
159}
160
161vector displacePolabel(vector x0, vector x_low, vector x_up,
162 double mux_low, double mux_up, double muy_low, double muy_up, double muz_low,
163 double muz_up)
164{
165 vector direction = x_up - x_low;
166 double t0;
167 double t1;
168 double t2;
169 vector x_low_def(x_low[0] + mux_low, x_low[1] + muy_low, x_low[2] + muz_low);
170 vector x_up_def(x_up[0] + mux_up, x_up[1] + muy_up, x_up[2] + muz_up);
171 vector direction_def = x_up_def - x_low_def;
172
173 if (abs(direction[0]) > 1e-16)
174 {
175 t0 = (x0[0] - x_low[0]) / direction[0];
176 }
177 else
178 {
179 t0 = 0;
180 }
181
182 if (abs(direction[1]) > 1e-16)
183 {
184 t1 = (x0[1] - x_low[1]) / direction[1];
185
186 if (t0 == 0)
187 {
188 t0 = t1;
189 }
190 }
191 else
192 {
193 t1 = t0;
194 }
195
196 if (abs(direction[2]) > 1e-16)
197 {
198 t2 = (x0[2] - x_low[2]) / direction[2];
199
200 if (t1 == 0)
201 {
202 t1 = t2;
203 }
204
205 if (t0 == 0)
206 {
207 t0 = t2;
208 }
209 }
210 else
211 {
212 t2 = t1;
213 }
214
215 Info << abs((x_low + t0 * direction - x0)[0]) << endl;
216 Info << abs((x_low + t1 * direction - x0)[1]) << endl;
217 Info << abs((x_low + t2 * direction - x0)[2]) << endl;
218 M_Assert(abs(abs((x_low + t0 * direction - x0)[0]) + abs((
219 x_low + t0 * direction - x0)[1]) + abs((x_low + t0 * direction - x0)[2])) <
220 1e-6, "The givent polabel is not on the segment");
221 vector def_polabel = x_low_def + t1 * direction_def;
222 Info << def_polabel << endl;
223 return def_polabel;
224}
225
226Field<vector> rotateMesh(fvMesh& mesh, double r1, double r2,
227 vector axis,
228 double alpha, labelList movingPointsIDs,
229 List<double> radii, word angleVariationMethod, double v)
230{
231 M_Assert(angleVariationMethod == "Linear"
232 || angleVariationMethod == "Sinusoidal" || angleVariationMethod == "Sigmoid",
233 "The variation function of the angle from the inner radius to the outer radius must be either Linear or Sinusoidal or Sigmoid");
234 Field<vector> pointRot(mesh.points());
235
236 for (label i = 0; i < movingPointsIDs.size(); i++)
237 {
238 double l = radii[i];
239 vector pointNow = pointRot[movingPointsIDs[i]];
240
241 if (l <= r1)
242 {
243 double theta = alpha / 180 * constant::mathematical::pi;
244 quaternion q(axis, theta);
245 pointRot[movingPointsIDs[i]] = q.transform(pointNow);
246 }
247 else if (l > r1 && l <= r2)
248 {
249 if (angleVariationMethod == "Linear")
250 {
251 double theta = alpha / 180 * constant::mathematical::pi * (r2 - l) / (r2 - r1);
252 quaternion q(axis, theta);
253 pointRot[movingPointsIDs[i]] = q.transform(pointNow);
254 }
255 else if (angleVariationMethod == "Sinusoidal")
256 {
257 double theta = alpha / 180 * constant::mathematical::pi * std::sin(
258 constant::mathematical::pi / 2 * (r2 - l) / (r2 - r1));
259 quaternion q(axis, theta);
260 pointRot[movingPointsIDs[i]] = q.transform(pointNow);
261 }
262 else if (angleVariationMethod == "Sigmoid")
263 {
264 double theta = alpha / 180 * constant::mathematical::pi * (1 - 1 /
265 (1 + std::exp(
266 -v * (l - (r1 + r2) / 2))));
267 quaternion q(axis, theta);
268 pointRot[movingPointsIDs[i]] = q.transform(pointNow);
269 }
270 }
271 }
272
273 return pointRot;
274}
275
276Eigen::MatrixXd rotationMatrix(vector AxisOfRotation,
277 double AngleOfRotation)
278{
279 Eigen::MatrixXd R(3, 3);
280 double theta = AngleOfRotation / 180 * constant::mathematical::pi;
281 scalar di = mag(AxisOfRotation);
282 scalar ux = AxisOfRotation[0] / di;
283 scalar uy = AxisOfRotation[1] / di;
284 scalar uz = AxisOfRotation[2] / di;
285 R(0, 0) = Foam::cos(theta) + ux * ux * (1 - Foam::cos(theta));
286 R(1, 0) = uy * ux * (1 - Foam::cos(theta)) + uz * Foam::sin(theta);
287 R(2, 0) = uz * ux * (1 - Foam::cos(theta)) - uy * Foam::sin(theta);
288 R(0, 1) = ux * uz * (1 - Foam::cos(theta)) - uz * Foam::sin(theta);
289 R(1, 1) = Foam::cos(theta) + uy * uy * (1 - Foam::cos(theta));
290 R(2, 1) = ux * uy * (1 - Foam::cos(theta)) + ux * Foam::sin(theta);
291 R(0, 2) = ux * uz * (1 - Foam::cos(theta)) + uy * Foam::sin(theta);
292 R(1, 2) = uy * uz * (1 - Foam::cos(theta)) - ux * Foam::sin(theta);
293 R(2, 2) = Foam::cos(theta) + uz * uz * (1 - Foam::cos(theta));
294 return R;
295}
296
298 fvMesh& mesh, label BC_ind)
299{
300 Eigen::VectorXd cellFaceDistance;
301 const polyPatch& cPatch = mesh.boundaryMesh()[BC_ind];
302 //Starting index of the face in a patch
303 label faceId_start = cPatch.start() ;
304 //List of cells close to a boundary
305 const labelUList& faceCells = cPatch.faceCells();
306 cellFaceDistance.conservativeResize(cPatch.size());
307 forAll(cPatch, faceI)
308 {
309 // index of each face
310 label faceID = faceId_start + faceI;
311 //id of the owner cell having the face
312 label faceOwner = faceCells[faceI] ;
313 cellFaceDistance(faceI) = mag(mesh.C()[faceOwner] - mesh.Cf()[faceID]);
314 }
315
316 return (cellFaceDistance);
317}
318
319List<label> getIndicesFromDisc(const fvMesh& mesh, double radius,
320 vector origin, vector axis, List<double>& radii)
321{
322 pointField meshPoints(mesh.points());
323 List<label> indices(meshPoints.size());
324 radii.resize(meshPoints.size());
325 label k = 0;
326
327 for (label i = 0; i < meshPoints.size(); i++)
328 {
329 vector pointNow = meshPoints[i];
330 vector r = pointNow - origin;
331 vector projComponent = (r & axis) / (pow(mag(axis), 2)) * axis;
332 vector d = r - projComponent;
333 double l = Foam::sqrt(pow(d[0],
334 2) + pow(d[1], 2) + pow(d[2], 2));
335
336 if (l < radius)
337 {
338 indices[k] = i;
339 radii[k] = l;
340 k++;
341 }
342 }
343
344 indices.resize(k);
345 radii.resize(k);
346 return indices;
347}
348
349template<typename type_f>
351 GeometricField<type_f, fvPatchField, volMesh>& field, Eigen::MatrixXd Box)
352{
353 M_Assert(Box.rows() == 2
354 && Box.cols() == 3,
355 "The box must be a 2*3 matrix shaped in this way: \nBox = \t|x0, y0, z0|\n\t|x1, yi, z1|\n");
356 List<label> indices(field.internalField().size());
357 int k = 0;
358
359 for (label i = 0; i < field.internalField().size(); i++)
360 {
361 auto cx = field.mesh().C()[i][0];
362 auto cy = field.mesh().C()[i][1];
363 auto cz = field.mesh().C()[i][2];
364
365 if (cx >= Box(0, 0) && cy >= Box(0, 1) && cz >= Box(0, 2) && cx <= Box(1, 0)
366 && cy <= Box(1, 1) && cz <= Box(1, 2) )
367 {
368 indices[k] = i;
369 k++;
370 }
371 }
372
373 indices.resize(k);
374 return indices;
375}
376
377template List<label> getIndicesFromBox(
378 GeometricField<scalar, fvPatchField, volMesh>& field, Eigen::MatrixXd Box);
379template List<label> getIndicesFromBox(
380 GeometricField<vector, fvPatchField, volMesh>& field, Eigen::MatrixXd Box);
381
382template<typename type_f>
383fvMeshSubset* getSubMeshFromBox(
384 GeometricField<type_f, fvPatchField, volMesh>& field, Eigen::MatrixXd Box)
385{
386 List<label> indices = getIndicesFromBox(field, Box);
387 fvMeshSubset* sub;
388 sub = new fvMeshSubset(field.mesh());
389 (field.mesh());
390#if OPENFOAM >= 1812
391 sub->setCellSubset(indices);
392#else
393 sub->setLargeCellSubset(indices);
394#endif
395 return sub;
396}
397
398template fvMeshSubset* getSubMeshFromBox(
399 GeometricField<scalar, fvPatchField, volMesh>& field, Eigen::MatrixXd Box);
400template fvMeshSubset* getSubMeshFromBox(
401 GeometricField<vector, fvPatchField, volMesh>& field, Eigen::MatrixXd Box);
402
403volScalarField meshNonOrtho(fvMesh& mesh,
404 volScalarField& NonOrtho)
405{
406 scalarField sno = (polyMeshTools::faceOrthogonality(mesh, mesh.Sf(),
407 mesh.C())).ref();
408
409 for (label i = 0; i < sno.size(); i++)
410 {
411 sno[i] = Foam::acos(min(1, sno[i])) * 180 / constant::mathematical::pi;
412 }
413
414 surfaceScalarField pippo = mesh.magSf();
415 const fvPatchList& patches = mesh.boundary();
416
417 for (label i = 0; i < pippo.internalField().size(); i++)
418 {
419 pippo.ref()[i] = sno[i];
420 }
421
422 for (label i = 0; i < patches.size(); i++)
423 {
424 if ( patches[i].type() != "empty" )
425 {
426 label start = patches[i].patch().start();
427 label n = patches[i].patch().size();
428
429 for (label k = 0; k < n; k++)
430 {
431 pippo.boundaryFieldRef()[i][k] = sno[start + k];
432 }
433 }
434 }
435
436 NonOrtho = fvc::average(pippo);
437 return NonOrtho;
438}
439
440List<vector> rotatePoints(const List<vector>& originalPoints,
441 vector AxisOfRotation, double AngleOfRotation)
442{
443 double theta = AngleOfRotation / 180 * constant::mathematical::pi;
444 quaternion q(AxisOfRotation, theta);
445 List<vector> rotatedPoints(originalPoints);
446
447 for (label i = 0; i < rotatedPoints.size(); i++)
448 {
449 rotatedPoints[i] = q.transform(rotatedPoints[i]);
450 }
451
452 return rotatedPoints;
453}
454}
forAll(example_CG.gList, solutionI)
Definition CGtest.H:21
Foam::fvMesh & mesh
Definition createMesh.H:47
#define M_Assert(Expr, Msg)
Header file of the geometry namespace.
volScalarField & v
Namespace to implement some useful assign operation of OF fields.
Field< vector > rotateMesh(fvMesh &mesh, double r1, double r2, vector axis, double alpha, labelList movingPointsIDs, List< double > radii, word angleVariationMethod, double v)
A function that rotates the mesh rigidly, by a fixed specified angle for the points lying within a di...
List< label > getIndices(const fvMesh &mesh, int index, int layers)
Gets the indices of the cells around a certain cell.
vector displacePolabel(vector x0, vector x_low, vector x_up, double mux_low, double mux_up, double muy_low, double muy_up, double muz_low, double muz_up)
Displace a Polabel belonging to a given segment.
fvMeshSubset * getSubMeshFromBox(GeometricField< type_f, fvPatchField, volMesh > &field, Eigen::MatrixXd Box)
Gets a subMesh from a box of coordinates and a given field (used only for the mesh).
Eigen::MatrixXd rotationMatrix(vector AxisOfRotation, double AngleOfRotation)
Functions that return a Rotation Matrix given an axis of rotation and an angle in degrees.
List< vector > displacedSegment(List< vector > x0, double mux1, double mux2, double muy1, double muy2)
Get position of displaced segment of points given the displacements of the end points.
List< label > getIndicesFromDisc(const fvMesh &mesh, double radius, vector origin, vector axis, List< double > &radii)
Gets the indices of the points which are inside a disc of a specified radius before carrying out a ro...
volScalarField meshNonOrtho(fvMesh &mesh, volScalarField &NonOrtho)
Returns a scalarField that containes the non-orthogonality value of a given mesh.
void getPointsFromPatch(fvMesh &mesh, label ind, List< vector > &points, labelList &indices)
Get the polabel coordinates and indices from patch.
labelList getIndicesFromBox(const fvMesh &mesh, List< label > indices, Eigen::MatrixXd Box, List< vector > &points2Move)
Gives the indices conteined into a defined box.
Eigen::VectorXd boudaryFaceToCellDistance(fvMesh &mesh, label BC_ind)
Compute the distance between the boundary face center and the boundary cell center.
List< vector > rotatePoints(const List< vector > &originalPoints, vector AxisOfRotation, double AngleOfRotation)
Rotate a list of points in clockwise direction given an axis of rotation and an angle in degrees.
label i
Definition pEqn.H:46