transformPoints.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2017-2022 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 Application
28  transformPoints
29 
30 Group
31  grpMeshManipulationUtilities
32 
33 Description
34  Transforms the mesh points in the polyMesh directory according to the
35  translate, rotate and scale options.
36 
37 Usage
38  Options are:
39 
40  -time value
41  Specify the time to search from and apply the transformation
42  (default is latest)
43 
44  -recentre
45  Recentre using the bounding box centre before other operations
46 
47  -translate vector
48  Translate the points by the given vector before rotations
49 
50  -rotate (vector vector)
51  Rotate the points from the first vector to the second
52 
53  -rotate-angle (vector angle)
54  Rotate angle degrees about vector axis.
55 
56  -rotate-x angle
57  Rotate (degrees) about x-axis.
58 
59  -rotate-y angle
60  Rotate (degrees) about y-axis.
61 
62  -rotate-z angle
63  Rotate (degrees) about z-axis.
64 
65  or -yawPitchRoll : (yaw pitch roll) degrees
66  or -rollPitchYaw : (roll pitch yaw) degrees
67 
68  -scale scalar|vector
69  Scale the points by the given scalar or vector on output.
70 
71  The any or all of the three options may be specified and are processed
72  in the above order.
73 
74  With -rotateFields (in combination with -rotate/yawPitchRoll/rollPitchYaw)
75  it will also read & transform vector & tensor fields.
76 
77 Note
78  roll (rotation about x)
79  pitch (rotation about y)
80  yaw (rotation about z)
81 
82 \*---------------------------------------------------------------------------*/
83 
84 #include "argList.H"
85 #include "Time.H"
86 #include "fvMesh.H"
87 #include "volFields.H"
88 #include "surfaceFields.H"
89 #include "pointFields.H"
90 #include "ReadFields.H"
91 #include "regionProperties.H"
92 #include "transformField.H"
94 #include "axisAngleRotation.H"
96 
97 using namespace Foam;
98 using namespace Foam::coordinateRotations;
99 
100 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
101 
102 template<class GeoField>
103 void readAndRotateFields
104 (
105  PtrList<GeoField>& flds,
106  const fvMesh& mesh,
107  const dimensionedTensor& rotT,
108  const IOobjectList& objects
109 )
110 {
111  ReadFields(mesh, objects, flds);
112  for (GeoField& fld : flds)
113  {
114  Info<< "Transforming " << fld.name() << endl;
115  transform(fld, rotT, fld);
116  }
117 }
118 
119 
120 void rotateFields
121 (
122  const word& regionName,
123  const Time& runTime,
124  const tensor& rotT
125 )
126 {
127  // Need dimensionedTensor for geometric fields
128  const dimensionedTensor T(rotT);
129 
130  #include "createRegionMesh.H"
131 
132  // Read objects in time directory
133  IOobjectList objects(mesh, runTime.timeName());
134 
135  // Read vol fields.
136 
138  readAndRotateFields(vsFlds, mesh, T, objects);
139 
141  readAndRotateFields(vvFlds, mesh, T, objects);
142 
144  readAndRotateFields(vstFlds, mesh, T, objects);
145 
146  PtrList<volSymmTensorField> vsymtFlds;
147  readAndRotateFields(vsymtFlds, mesh, T, objects);
148 
150  readAndRotateFields(vtFlds, mesh, T, objects);
151 
152  // Read surface fields.
153 
155  readAndRotateFields(ssFlds, mesh, T, objects);
156 
158  readAndRotateFields(svFlds, mesh, T, objects);
159 
161  readAndRotateFields(sstFlds, mesh, T, objects);
162 
164  readAndRotateFields(ssymtFlds, mesh, T, objects);
165 
167  readAndRotateFields(stFlds, mesh, T, objects);
168 
169  mesh.write();
170 }
171 
172 
173 // Retrieve scaling option
174 // - size 0 : no scaling
175 // - size 1 : uniform scaling
176 // - size 3 : non-uniform scaling
177 List<scalar> getScalingOpt(const word& optName, const argList& args)
178 {
179  // readListIfPresent handles single or multiple values
180  // - accept 1 or 3 values
181 
182  List<scalar> scaling;
183  args.readListIfPresent(optName, scaling);
184 
185  if (scaling.size() == 1)
186  {
187  // Uniform scaling
188  }
189  else if (scaling.size() == 3)
190  {
191  // Non-uniform, but may actually be uniform
192  if
193  (
194  equal(scaling[0], scaling[1])
195  && equal(scaling[0], scaling[2])
196  )
197  {
198  scaling.resize(1);
199  }
200  }
201  else if (!scaling.empty())
202  {
203  FatalError
204  << "Incorrect number of components, must be 1 or 3." << nl
205  << " -" << optName << ' ' << args[optName].c_str() << endl
206  << exit(FatalError);
207  }
208 
209  if (scaling.size() == 1 && equal(scaling[0], 1))
210  {
211  // Scale factor 1 == no scaling
212  scaling.clear();
213  }
214 
215  // Zero and negative scaling are permitted
216 
217  return scaling;
218 }
219 
220 
221 void applyScaling(pointField& points, const List<scalar>& scaling)
222 {
223  if (scaling.size() == 1)
224  {
225  Info<< "Scaling points uniformly by " << scaling[0] << nl;
226  points *= scaling[0];
227  }
228  else if (scaling.size() == 3)
229  {
230  const vector factor(scaling[0], scaling[1], scaling[2]);
231  Info<< "Scaling points by " << factor << nl;
232  cmptMultiply(points, points, factor);
233  }
234 }
235 
236 
237 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
238 
239 int main(int argc, char *argv[])
240 {
242  (
243  "Transform (translate / rotate / scale) mesh points.\n"
244  "Note: roll=rotate about x, pitch=rotate about y, yaw=rotate about z"
245  );
247  (
248  "time",
249  "time",
250  "Specify the time to search from and apply the transformation"
251  " (default is latest)"
252  );
254  (
255  "recentre",
256  "Recentre the bounding box before other operations"
257  );
259  (
260  "translate",
261  "vector",
262  "Translate by specified <vector> before rotations"
263  );
265  (
266  "auto-centre",
267  "Use bounding box centre as centre for rotations"
268  );
270  (
271  "centre",
272  "point",
273  "Use specified <point> as centre for rotations"
274  );
275  argList::addOptionCompat("auto-centre", {"auto-origin", 2206});
276  argList::addOptionCompat("centre", {"origin", 2206});
277 
279  (
280  "rotate",
281  "(vectorA vectorB)",
282  "Rotate from <vectorA> to <vectorB> - eg, '((1 0 0) (0 0 1))'"
283  );
285  (
286  "rotate-angle",
287  "(vector angle)",
288  "Rotate <angle> degrees about <vector> - eg, '((1 0 0) 45)'"
289  );
291  (
292  "rotate-x", "deg",
293  "Rotate (degrees) about x-axis"
294  );
296  (
297  "rotate-y", "deg",
298  "Rotate (degrees) about y-axis"
299  );
301  (
302  "rotate-z", "deg",
303  "Rotate (degrees) about z-axis"
304  );
306  (
307  "rollPitchYaw",
308  "vector",
309  "Rotate by '(roll pitch yaw)' degrees"
310  );
312  (
313  "yawPitchRoll",
314  "vector",
315  "Rotate by '(yaw pitch roll)' degrees"
316  );
318  (
319  "rotateFields",
320  "Read and transform vector and tensor fields too"
321  );
323  (
324  "scale",
325  "scalar | vector",
326  "Scale by the specified amount - Eg, for uniform [mm] to [m] scaling "
327  "use either '(0.001 0.001 0.001)' or simply '0.001'"
328  );
329 
330  // Compatibility with surfaceTransformPoints
331  argList::addOptionCompat("scale", {"write-scale", 0});
332 
333  #include "addAllRegionOptions.H"
334  #include "setRootCase.H"
335 
336  const bool doRotateFields = args.found("rotateFields");
337 
338  // Verify that an operation has been specified
339  {
340  const List<word> operationNames
341  ({
342  "recentre",
343  "translate",
344  "rotate",
345  "rotate-angle",
346  "rotate-x",
347  "rotate-y",
348  "rotate-z",
349  "rollPitchYaw",
350  "yawPitchRoll",
351  "scale"
352  });
353 
354  if (!args.count(operationNames))
355  {
356  FatalError
357  << "No operation supplied, "
358  << "use at least one of the following:" << nl
359  << " ";
360 
361  for (const auto& opName : operationNames)
362  {
363  FatalError
364  << " -" << opName;
365  }
366 
367  FatalError
368  << nl << exit(FatalError);
369  }
370  }
371 
372  // ------------------------------------------------------------------------
373 
374  #include "createTime.H"
375 
376  if (args.found("time"))
377  {
378  if (args["time"] == "constant")
379  {
380  runTime.setTime(instant(0, "constant"), 0);
381  }
382  else
383  {
384  const scalar timeValue = args.get<scalar>("time");
385  runTime.setTime(instant(timeValue), 0);
386  }
387  }
388 
389  // Handle -allRegions, -regions, -region
390  #include "getAllRegionOptions.H"
391 
392  // ------------------------------------------------------------------------
393 
394  forAll(regionNames, regioni)
395  {
396  const word& regionName = regionNames[regioni];
397  const fileName meshDir
398  (
400  );
401 
402  if (regionNames.size() > 1)
403  {
404  Info<< "region=" << regionName << nl;
405  }
406 
408  (
409  IOobject
410  (
411  "points",
412  runTime.findInstance(meshDir, "points"),
413  meshDir,
414  runTime,
418  )
419  );
420 
421 
422  // Begin operations
423 
424  vector v;
425  if (args.found("recentre"))
426  {
427  v = boundBox(points).centre();
428  Info<< "Adjust centre " << v << " -> (0 0 0)" << endl;
429  points -= v;
430  }
431 
432  if (args.readIfPresent("translate", v))
433  {
434  Info<< "Translating points by " << v << endl;
435  points += v;
436  }
437 
438  vector rotationCentre;
439  bool useRotationCentre = args.readIfPresent("centre", rotationCentre);
440  if (args.found("auto-centre") && !useRotationCentre)
441  {
442  useRotationCentre = true;
443  rotationCentre = boundBox(points).centre();
444  }
445 
446  if (useRotationCentre)
447  {
448  Info<< "Set centre of rotation to " << rotationCentre << endl;
449  points -= rotationCentre;
450  }
451 
452 
453  // Get a rotation specification
454 
455  tensor rot(Zero);
456  bool useRotation(false);
457 
458  if (args.found("rotate"))
459  {
460  Pair<vector> n1n2
461  (
462  args.lookup("rotate")()
463  );
464  n1n2[0].normalise();
465  n1n2[1].normalise();
466 
467  rot = rotationTensor(n1n2[0], n1n2[1]);
468  useRotation = true;
469  }
470  else if (args.found("rotate-angle"))
471  {
472  const Tuple2<vector, scalar> rotAxisAngle
473  (
474  args.lookup("rotate-angle")()
475  );
476 
477  const vector& axis = rotAxisAngle.first();
478  const scalar angle = rotAxisAngle.second();
479 
480  Info<< "Rotating points " << nl
481  << " about " << axis << nl
482  << " angle " << angle << nl;
483 
484  rot = axisAngle::rotation(axis, angle, true);
485  useRotation = true;
486  }
487  else if (args.found("rotate-x"))
488  {
489  const scalar angle = args.get<scalar>("rotate-x");
490 
491  Info<< "Rotating points about x-axis: " << angle << nl;
492 
493  rot = axisAngle::rotation(vector::X, angle, true);
494  useRotation = true;
495  }
496  else if (args.found("rotate-y"))
497  {
498  const scalar angle = args.get<scalar>("rotate-y");
499 
500  Info<< "Rotating points about y-axis: " << angle << nl;
501 
502  rot = axisAngle::rotation(vector::Y, angle, true);
503  useRotation = true;
504  }
505  else if (args.found("rotate-z"))
506  {
507  const scalar angle = args.get<scalar>("rotate-z");
508 
509  Info<< "Rotating points about z-axis: " << angle << nl;
510 
511  rot = axisAngle::rotation(vector::Z, angle, true);
512  useRotation = true;
513  }
514  else if (args.readIfPresent("rollPitchYaw", v))
515  {
516  Info<< "Rotating points by" << nl
517  << " roll " << v.x() << nl
518  << " pitch " << v.y() << nl
519  << " yaw " << v.z() << nl;
520 
521  rot = euler::rotation(euler::eulerOrder::ROLL_PITCH_YAW, v, true);
522  useRotation = true;
523  }
524  else if (args.readIfPresent("yawPitchRoll", v))
525  {
526  Info<< "Rotating points by" << nl
527  << " yaw " << v.x() << nl
528  << " pitch " << v.y() << nl
529  << " roll " << v.z() << nl;
530 
531  rot = euler::rotation(euler::eulerOrder::YAW_PITCH_ROLL, v, true);
532  useRotation = true;
533  }
534 
535  if (useRotation)
536  {
537  Info<< "Rotating points by " << rot << endl;
538  transform(points, rot, points);
539 
540  if (doRotateFields)
541  {
542  rotateFields(regionName, runTime, rot);
543  }
544  }
545 
546  if (useRotationCentre)
547  {
548  Info<< "Unset centre of rotation from " << rotationCentre << endl;
549  points += rotationCentre;
550  }
551 
552  // Output scaling
553  applyScaling(points, getScalingOpt("scale", args));
554 
555 
556  // Set the precision of the points data to 10
558 
559  Info<< "Writing points into directory "
560  << runTime.relativePath(points.path()) << nl
561  << endl;
562  points.write();
563  }
564 
565  Info<< nl << "End" << nl << endl;
566 
567  return 0;
568 }
569 
570 
571 // ************************************************************************* //
Foam::surfaceFields.
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:462
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
A class for handling file names.
Definition: fileName.H:71
wordList ReadFields(const typename GeoMesh::Mesh &mesh, const IOobjectList &objects, PtrList< GeometricField< Type, PatchField, GeoMesh >> &fields, const bool syncPar=true, const bool readOldTime=false)
Read Geometric fields of templated type.
List of IOobjects with searching and retrieving facilities. Implemented as a HashTable, so the various sorted methods should be used if traversing in parallel.
Definition: IOobjectList.H:55
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
word findInstance(const fileName &dir, const word &name=word::null, IOobjectOption::readOption rOpt=IOobjectOption::MUST_READ, const word &stopInstance=word::null) const
Return time instance (location) of dir that contains the file name (eg, used in reading mesh data)...
Definition: Time.C:787
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:132
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
Spatial transformation functions for GeometricField.
bool equal(const T &a, const T &b)
Compare two values for equality.
Definition: label.H:164
const word & regionName() const
The mesh region name or word::null if polyMesh::defaultRegion.
Definition: polyMesh.C:842
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:632
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:402
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
fileName relativePath(const fileName &input, const bool caseTag=false) const
Return the input relative to the globalPath by stripping off a leading value of the globalPath...
Definition: TimePathsI.H:80
static unsigned int defaultPrecision() noexcept
Return the default precision.
Definition: IOstream.H:423
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition: argList.C:374
static void addOptionCompat(const word &optName, std::pair< const char *, int > compat)
Specify an alias for the option name.
Definition: argList.C:418
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
Field reading functions for post-processing utilities.
wordList regionNames
Generic dimensioned Type class.
Ignore writing from objectRegistry::writeObject()
tensor rotationTensor(const vector &n1, const vector &n2)
Rotational transformation tensor from vector n1 to n2.
Definition: transform.H:47
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
Spatial transformation functions for primitive fields.
Foam::word regionName(Foam::polyMesh::defaultRegion)
Namespace for coordinate system rotations.
Definition: axesRotation.C:30
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: instant.H:46
dynamicFvMesh & mesh
const pointField & points
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:109
A class for handling words, derived from Foam::string.
Definition: word.H:63
Extract command arguments and options from the supplied argc and argv parameters. ...
Definition: argList.H:118
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
Definition: argList.C:385
virtual void setTime(const Time &t)
Reset the time and time-index to those of the given time.
Definition: Time.C:997
ITstream lookup(const word &optName) const
Return an input stream from the named option.
Definition: argListI.H:177
virtual bool write(const bool writeOnProc=true) const
Write mesh using IO settings from time.
Definition: fvMesh.C:1069
dimensioned< Type > cmptMultiply(const dimensioned< Type > &, const dimensioned< Type > &)
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
static word timeName(const scalar t, const int precision=precision_)
Return time name of given scalar time formatted with the given precision.
Definition: Time.C:770
bool readListIfPresent(const word &optName, List< T > &list) const
If named option is present, get a List of values treating a single entry like a list of size 1...
Definition: argListI.H:387
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name...
Definition: instant.H:53
Required Variables.
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:271
static tensor rotation(const vector &angles, bool degrees=false)
Rotation tensor calculated for the intrinsic Euler angles in z-x-z order.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
PtrList< volScalarField > & Y
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:79
static tensor rotation(const vector &axis, const scalar angle, bool degrees=false)
The rotation tensor for given axis/angle.
messageStream Info
Information stream (stdout output on master, null elsewhere)
bool readIfPresent(const word &optName, T &val) const
Read a value from the named option if present.
Definition: argListI.H:316
point centre() const
The centre (midpoint) of the bounding box.
Definition: boundBoxI.H:186
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:521
Foam::argList args(argc, argv)
Tensor of scalars, i.e. Tensor<scalar>.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:171
A primitive field of type <T> with automated input and output.
label count(const UList< word > &optionNames) const
Return how many of the specified options were used.
Definition: argList.C:1967
Do not request registration (bool: false)
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:171
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:133