sweepFace.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "sweepFace.H"
27 #include "blockDescriptor.H"
28 #include "transform.H"
30 
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
35 namespace blockFaces
36 {
39 }
40 }
41 
42 
43 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44 
46 (
47  const dictionary& dict,
48  const label index,
49  const searchableSurfaceList& geometry,
50  Istream& is
51 )
52 :
53  blockFace(dict, index, is),
54  rotationFraction_(readScalar(is))
55 {
56  if (rotationFraction_ < 0 || rotationFraction_ > 1)
57  {
59  << "Rotation fraction for face " << vertices()
60  << " must be between 0 and 1"
61  << exit(FatalIOError);
62  }
63 }
64 
65 
66 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
67 
69 (
70  const blockDescriptor& desc,
71  const label blockFacei,
73 ) const
74 {
75  // Determine the extents of the two-dimensional grid of points
76  static const List<direction> blockFaceDirection0({2, 2, 2, 2, 1, 1});
77  static const List<direction> blockFaceDirection1({1, 1, 0, 0, 0, 0});
78  label nRows = desc.density()[blockFaceDirection0[blockFacei]] + 1;
79  label nCols = desc.density()[blockFaceDirection1[blockFacei]] + 1;
80 
81  // Based on the ordering of the user-supplied vertices, determine whether
82  // or not the grid is to be transposed, and therefore in which direction
83  // across the grid to sweep
84  bool transpose = false;
85  {
86  static const labelList blockFaceAnchorEdgeis({4, 5, 0, 1, 0, 3});
87  const edge anchorEdge =
88  desc.blockShape().edges()[blockFaceAnchorEdgeis[blockFacei]];
89  forAll(vertices(), i)
90  {
91  if (edge::compare(anchorEdge, vertices().faceEdge(i)) != 0)
92  {
93  transpose = i % 2;
94  break;
95  }
96  }
97  if (transpose) Swap(nRows, nCols);
98  }
99 
100  // Access a point by index. The index may be negative, in which case it
101  // will index in a reverse direction from the end, a-la python.
102  auto pi = [&](label i, label j)
103  {
104  if (i < 0) i = nRows + i;
105  if (j < 0) j = nCols + j;
106  return transpose ? j*nRows + i : i*nCols + j;
107  };
108  auto p = [&](label i, label j) -> point&
109  {
110  return points[pi(i, j)];
111  };
112 
113  // Determine the rotations *around* the edge for every row
114  scalarList dThetaAround(nRows);
115  for (label i = 1; i < nRows - 1; ++ i)
116  {
117  const vector axisi = normalised(p(i,-1) - p(i,0));
118  const tensor A = tensor::I - sqr(axisi);
119  const face fPrev({pi(i,0), pi(i,-1), pi(i-1,-1), pi(i-1,0)});
120  const face fNext({pi(i+1,0), pi(i+1,-1), pi(i,-1), pi(i,0)});
121  const vector aPrev = face::area(UIndirectList<point>(points, fPrev));
122  const vector aNext = face::area(UIndirectList<point>(points, fNext));
123  dThetaAround[i] =
124  asin((normalised(A & aPrev) ^ normalised(A & aNext)) & axisi);
125  }
126  scalarList thetaAround0(nRows), thetaAround1(nRows);
127  thetaAround0[0] = thetaAround1[nRows-1] = 0;
128  for (label i = 1; i < nRows - 1; ++ i)
129  {
130  thetaAround0[i] = thetaAround0[i-1] + dThetaAround[i];
131  }
132  for (label i = nRows - 2; i > 0; -- i)
133  {
134  thetaAround1[i] = thetaAround1[i+1] - dThetaAround[i];
135  }
136 
137  // Calculate the positions of the points in each row in turn
138  const vector axis0 = normalised(p(0,-1) - p(0,0));
139  const vector axis1 = normalised(p(-1,-1) - p(-1,0));
140  for (label i = 1; i < nRows - 1; ++ i)
141  {
142  // Rotation *of* the edge
143  const tensor Rof0 =
145  (
146  normalised(p(0,-1) - p(0,0)),
147  normalised(p(i,-1) - p(i,0))
148  );
149  const tensor Rof1 =
151  (
152  normalised(p(-1,-1) - p(-1,0)),
153  normalised(p(i,-1) - p(i,0))
154  );
155 
156  // Rotation *around* the edge
157  const tensor Raround0 = Ra(axis0, rotationFraction_*thetaAround0[i]);
158  const tensor Raround1 = Ra(axis1, rotationFraction_*thetaAround1[i]);
159 
160  // Scale factor
161  const scalar scale0 = mag(p(i,-1) - p(i,0))/mag(p(0,-1) - p(0,0));
162  const scalar scale1 = mag(p(i,-1) - p(i,0))/mag(p(-1,-1) - p(-1,0));
163 
164  // Combined transforms
165  const tensor T0 = Rof0 & Raround0 * scale0;
166  const tensor T1 = Rof1 & Raround1 * scale1;
167 
168  // Set the positions in the row
169  for (label j = 1; j < nCols - 1; ++ j)
170  {
171  const scalar fi = scalar(i)/(nRows - 1);
172  const scalar fj = scalar(j)/(nCols - 1);
173 
174  p(i,j) =
175  (1 - fi)*(1 - fj)*(p(i,0) + (T0 & (p(0,j) - p(0,0))))
176  + (1 - fi)*fj*(p(i,-1) + (T0 & (p(0,j) - p(0,-1))))
177  + fi*(1 - fj)*(p(i,0) + (T1 & (p(-1,j) - p(-1,0))))
178  + fi*fj*(p(i,-1) + (T1 & (p(-1,j) - p(-1,-1))));
179  }
180  }
181 }
182 
183 
184 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Macros for easy insertion into run-time selection tables.
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:91
static const Tensor I
Definition: Tensor.H:83
A List with indirect addressing.
Definition: UIndirectList.H:61
Takes the description of the block and the list of curved edges and creates a list of points on edges...
const cellShape & blockShape() const
Return the block shape.
const Vector< label > & density() const
Return the mesh density (number of cells) in the i,j,k directions.
Define a curved face.
Definition: blockFace.H:56
const face & vertices() const
Return block face vertices.
Definition: blockFaceI.H:28
This curved face sweeps the points of an opposing pair of the face's four edges over the surface of t...
Definition: sweepFace.H:75
virtual void project(const blockDescriptor &, const label blockFacei, pointField &points) const
Project the given points onto the surface.
Definition: sweepFace.C:69
sweepFace(const dictionary &dict, const label index, const searchableSurfaceList &geometry, Istream &)
Construct from Istream setting pointsList.
Definition: sweepFace.C:46
edgeList edges() const
Edges of this cellShape.
Definition: cellShapeI.H:241
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:61
static int compare(const edge &, const edge &)
Compare edges.
Definition: edgeI.H:36
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
static vector area(const PointField &ps)
Return vector area given face points.
Container for searchableSurfaces.
const scalar T0
#define readScalar
Definition: doubleScalar.C:39
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
const pointField & points
defineTypeNameAndDebug(projectFace, 0)
addToRunTimeSelectionTable(blockFace, projectFace, Istream)
static const coefficient A("A", dimPressure, 611.21)
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
dimensionedScalar asin(const dimensionedScalar &ds)
pointField vertices(const blockVertexList &bvl)
tensor rotationTensor(const vector &n1, const vector &n2)
Rotational transformation tensor from unit vector n1 to n2.
Definition: transform.H:47
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:59
tensor Ra(const vector &a, const scalar omega)
Rotational transformation tensor about axis a by omega radians.
Definition: transform.H:140
tmp< DimensionedField< typename outerProduct< Type, Type >::type, GeoMesh, Field >> sqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dimensionSet normalised(const dimensionSet &)
Definition: dimensionSet.C:509
IOerror FatalIOError
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
void Swap(T &a, T &b)
Definition: Swap.H:43
dictionary dict
volScalarField & p
3D tensor transformation operations.