lumpedPointMovement.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-2021 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 Application
27  lumpedPointMovement
28 
29 Description
30  This utility can be used to produce VTK files to visualize the response
31  points/rotations and the corresponding movement of the building surfaces.
32 
33  Uses the tabulated responses from the specified file.
34  Optionally, it can also be used to a dummy responder for the
35  externalFileCoupler logic, which makes it useful as a debugging facility
36  as well demonstrating how an external application could communicate
37  with the lumpedPointMovement point-patch boundary condition.
38 
39 \*---------------------------------------------------------------------------*/
40 
41 #include "argList.H"
42 #include "Time.H"
43 #include "OFstream.H"
44 #include "foamVtkSeriesWriter.H"
45 #include "lumpedPointTools.H"
46 #include "lumpedPointIOMovement.H"
47 
48 using namespace Foam;
49 
50 
51 inline List<lumpedPointStateTuple> getResponseTable
52 (
53  const fileName& file,
54  const lumpedPointState& state0
55 )
56 {
58  (
59  file,
60  state0.rotationOrder(),
61  state0.degrees()
62  );
63 }
64 
65 
66 void echoTableLimits
67 (
68  const List<lumpedPointStateTuple>& tbl,
69  const label span,
70  const label maxOut
71 )
72 {
73  Info<< "Using response table with " << tbl.size() << " entries" << nl;
74 
75  if (span)
76  {
77  Info<< "Increment input by " << span << nl;
78  }
79 
80  if (maxOut)
81  {
82  Info<< "Stopping after " << maxOut << " outputs" << nl;
83  }
84 }
85 
86 
87 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
88 
89 int main(int argc, char *argv[])
90 {
92  (
93  "Visualize lumpedPoint movements or provide a slave responder"
94  " for diagnostic purposes."
95  );
96 
97  argList::noFunctionObjects(); // Never use function objects
99  (
100  "max",
101  "N",
102  "Maximum number of outputs"
103  );
105  (
106  "span",
107  "N",
108  "Increment each input by N (default: 1)"
109  );
111  (
112  "scale",
113  "factor",
114  "Relaxation/scaling factor for movement (default: 1)"
115  );
117  (
118  "visual-length",
119  "len",
120  "Visualization length for planes (visualized as triangles)"
121  );
123  (
124  "Test movement without a mesh"
125  );
127  (
128  "removeLock",
129  "Remove lock-file on termination of slave"
130  );
132  (
133  "slave",
134  "Invoke as a slave responder for testing"
135  );
136  argList::addArgument("responseFile");
137 
138  #include "setRootCase.H"
139 
140  const label maxOut = Foam::max(0, args.getOrDefault<label>("max", 0));
141  const label span = Foam::max(1, args.getOrDefault<label>("span", 1));
142 
143  // Control parameters
144  const bool dryrun = args.dryRun();
145  const bool slave = args.found("slave");
146  const bool removeLock = args.found("removeLock");
147 
148  const scalar relax = args.getOrDefault<scalar>("scale", 1);
149 
151 
152  const auto responseFile = args.get<fileName>(1);
153 
154  // ----------------------------------------------------------------------
155  // Slave mode
156  // ----------------------------------------------------------------------
157 
158  if (slave)
159  {
160  Info<< "Running as slave responder" << endl;
161 
162  if (Pstream::parRun())
163  {
165  << "Running as slave responder is not permitted in parallel"
166  << nl
167  << exit(FatalError);
168  }
169 
170  #include "createTime.H"
171 
172  // Create movement without a mesh
173  autoPtr<lumpedPointIOMovement> movementPtr =
175 
176  if (!movementPtr)
177  {
178  Info<< "No valid movement found" << endl;
179  return 1;
180  }
181  auto& movement = *movementPtr;
182 
183  // Reference state0
184  const lumpedPointState& state0 = movement.state0();
185 
186  List<lumpedPointStateTuple> responseTable =
187  getResponseTable(responseFile, state0);
188 
189  echoTableLimits(responseTable, span, maxOut);
190 
191  if (dryrun)
192  {
193  Info<< "dry-run: response table with " << responseTable.size()
194  << " entries" << nl
195  << "\nEnd\n" << endl;
196  return 0;
197  }
198 
199  externalFileCoupler& coupler = movement.coupler();
200 
201  for
202  (
203  label timei = 0, outputCount = 0;
204  timei < responseTable.size();
205  timei += span
206  )
207  {
208  Info<< args.executable() << ": waiting for master" << endl;
209 
210  // Wait for master, but stop if status=done was seen
211  if (!coupler.waitForMaster())
212  {
213  Info<< args.executable()
214  << ": stopping status=done was detected" << endl;
215  break;
216  }
217 
218  lumpedPointState state = responseTable[timei].second();
219  state.relax(relax, state0);
220 
221  // Generate input for OpenFOAM
222  OFstream os(coupler.resolveFile(movement.inputName()));
223  if
224  (
225  movement.inputFormat()
227  )
228  {
229  state.writePlain(os);
230  }
231  else
232  {
233  os.writeEntry("time", responseTable[timei].first());
234  state.writeDict(os);
235  }
236 
237  Info<< args.executable()
238  << ": updated to state " << timei
239  << " - switch to master"
240  << endl;
241 
242  // Let OpenFOAM know that it can continue
243  coupler.useMaster();
244 
245  ++outputCount;
246 
247  if (maxOut && outputCount >= maxOut)
248  {
249  Info<< args.executable()
250  << ": stopping after " << maxOut << " outputs" << endl;
251  break;
252  }
253  }
254 
255  if (removeLock)
256  {
257  Info<< args.executable() << ": removing lock file" << endl;
258  coupler.useSlave(); // This removes the lock-file
259  }
260 
261  Info<< args.executable() << ": finishing" << nl;
262 
263  Info<< "\nEnd\n" << endl;
264  return 0;
265  }
266 
267 
268  // ----------------------------------------------------------------------
269  // dry-run
270  // ----------------------------------------------------------------------
271 
272  if (dryrun)
273  {
274  Info<< "dry-run: creating states only" << nl;
275 
276  #include "createTime.H"
277 
278  // Create movement without a mesh
279  autoPtr<lumpedPointIOMovement> movementPtr =
281 
282  if (!movementPtr)
283  {
284  Info<< "No valid movement found" << endl;
285  return 1;
286  }
287  auto& movement = *movementPtr;
288 
289  // Reference state0
290  const lumpedPointState& state0 = movement.state0();
291 
292  List<lumpedPointStateTuple> responseTable =
293  getResponseTable(responseFile, state0);
294 
295  echoTableLimits(responseTable, span, maxOut);
296 
297 
298  vtk::seriesWriter stateSeries;
299 
300  for
301  (
302  label timei = 0, outputCount = 0;
303  timei < responseTable.size();
304  timei += span
305  )
306  {
307  lumpedPointState state = responseTable[timei].second();
308 
309  state += movement.origin();
310  movement.scalePoints(state);
311  state.relax(relax, state0);
312 
313  Info<< "output [" << timei << '/' << responseTable.size() << ']';
314 
315  // State/response = what comes back from FEM
316  {
317  const word outputName =
318  word::printf("state_%06d.vtp", outputCount);
319 
320  Info<< " " << outputName;
321 
322  movement.writeStateVTP(state, outputName);
323  stateSeries.append(outputCount, outputName);
324  }
325 
326  Info<< endl;
327 
328  ++outputCount;
329 
330  if (maxOut && outputCount >= maxOut)
331  {
332  Info<< "Max output " << maxOut << " ... stopping" << endl;
333  break;
334  }
335  }
336 
337  // Write file series
338 
339  if (stateSeries.size())
340  {
341  Info<< nl << "write state.vtp.series" << nl;
342  stateSeries.write("state.vtp");
343  }
344 
345  Info<< "\nEnd\n" << endl;
346  return 0;
347  }
348 
349 
350  // ----------------------------------------------------------------------
351  // test patch movement
352  // ----------------------------------------------------------------------
353 
354  #include "createTime.H"
355 
357 
358  #include "createNamedMesh.H"
359 
360  // Create movement with mesh
361  autoPtr<lumpedPointIOMovement> movementPtr =
363 
364  if (!movementPtr)
365  {
366  Info<< "No valid movement found" << endl;
367  return 1;
368  }
369  auto& movement = *movementPtr;
370 
371  // Reference state0
372  const lumpedPointState& state0 = movement.state0();
373 
374  List<lumpedPointStateTuple> responseTable =
375  getResponseTable(responseFile, state0);
376 
377  echoTableLimits(responseTable, span, maxOut);
378 
380 
382  if (!nPatches)
383  {
384  Info<< "No point patches with lumped movement found" << endl;
385  return 2;
386  }
387 
388  Info<< "Lumped point patch controls set on "
389  << nPatches << " patches" << nl;
390 
392 
393 
394  // Output vtk file series
395  vtk::seriesWriter stateSeries;
396  vtk::seriesWriter geomSeries;
397 
398  // Initial geometry
399  movement.writeVTP("geom_init.vtp", state0, mesh, points0);
400 
402 
403  for
404  (
405  label timei = 0, outputCount = 0;
406  timei < responseTable.size();
407  timei += span
408  )
409  {
410  lumpedPointState state = responseTable[timei].second();
411 
412  state += movement.origin();
413  movement.scalePoints(state);
414  state.relax(relax, state0);
415 
416  Info<< "output [" << timei << '/' << responseTable.size() << ']';
417 
418  // State/response = what comes back from FEM
419  {
420  const word outputName =
421  word::printf("state_%06d.vtp", outputCount);
422 
423  Info<< " " << outputName;
424 
425  movement.writeStateVTP(state, outputName);
426  stateSeries.append(outputCount, outputName);
427  }
428 
429  {
430  const word outputName =
431  word::printf("geom_%06d.vtp", outputCount);
432 
433  Info<< " " << outputName;
434 
435  movement.writeVTP(outputName, state, mesh, points0);
436  geomSeries.append(outputCount, outputName);
437  }
438 
439  Info<< endl;
440 
441  ++outputCount;
442 
443  if (maxOut && outputCount >= maxOut)
444  {
445  Info<< "Max output " << maxOut << " ... stopping" << endl;
446  break;
447  }
448  }
449 
450 
451  // Write file series
452 
453  if (geomSeries.size())
454  {
455  Info<< nl << "write geom.vtp.series" << nl;
456  geomSeries.write("geom.vtp");
457  }
458  if (stateSeries.size())
459  {
460  Info<< nl << "write state.vtp.series" << nl;
461  stateSeries.write("state.vtp");
462  }
463 
464  Info<< "\nEnd\n" << endl;
465 
466  return 0;
467 }
468 
469 
470 // ************************************************************************* //
label nPatches
Definition: readKivaGrid.H:396
enum Time::stopAtControls waitForMaster() const
Wait for master to complete.
static void noFunctionObjects(bool addWithOption=false)
Remove &#39;-noFunctionObjects&#39; option and ignore any occurrences.
Definition: argList.C:547
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
List< lumpedPointStateTuple > lumpedPointStates(const dictionary &dict, quaternion::eulerOrder rotOrder=quaternion::eulerOrder::ZXZ, bool degrees=false)
Load a list of states from a dictionary.
Encapsulates the logic for coordinating between OpenFOAM and an external application.
A class for handling file names.
Definition: fileName.H:72
enum Time::stopAtControls useSlave(const bool wait=false) const
Remove lock file to indicate that the external program is in charge.
label size() const noexcept
The number of data sets.
static scalar visLength
The length for visualization triangles.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
UEqn relax()
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
quaternion::eulerOrder rotationOrder() const
The Euler-angle rotation order.
void writeDict(Ostream &os) const
Output as dictionary content.
void writePlain(Ostream &os) const
Output as plain content.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
Output to file stream, using an OSstream.
Definition: OFstream.H:49
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
pointIOField points0Field(const polyMesh &mesh)
Return the 0 or constant points field.
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1049
Required Classes.
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
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:321
"plain" is a simple ASCII format
T getOrDefault(const word &optName, const T &deflt) const
Get a value from the named option if present, or return default.
Definition: argListI.H:300
word outputName("finiteArea-edges.obj")
dynamicFvMesh & mesh
Provides a means of accumulating and generating VTK file series.
A class for handling words, derived from Foam::string.
Definition: word.H:63
static void addDryRunOption(const string &usage, bool advanced=false)
Enable a &#39;dry-run&#39; bool option, with usage information.
Definition: argList.C:504
const word & executable() const noexcept
Name of executable without the path.
Definition: argListI.H:44
int dryRun() const noexcept
Return the dry-run flag.
Definition: argListI.H:109
enum Time::stopAtControls useMaster(const bool wait=false) const
Create lock file to indicate that OpenFOAM is in charge.
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:935
fileName resolveFile(const word &file) const
Return the file path in the communications directory.
static word printf(const char *fmt, const PrimitiveType &val)
Use a printf-style formatter for a primitive.
bool degrees() const
Rotation angles in degrees.
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:112
OBJstream os(runTime.globalPath()/outputName)
void scalePoints(const scalar scaleFactor)
Scale points by given factor.
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name...
Definition: instant.H:53
pointField points0(pointIOField(IOobject("points", mesh.time().constant(), polyMesh::meshSubDir, mesh, IOobject::MUST_READ, IOobject::NO_WRITE, IOobject::NO_REGISTER)))
label setPatchControls(const pointVectorField &pvf, const pointField &points0)
Return the patch-ids associated with a "lumpedPointDisplacement" type.
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:271
void relax(const scalar alpha, const lumpedPointState &prev)
Relax the state.
static void write(const fileName &base, const UList< instant > &series, const char sep='_')
Write file series (JSON format) to disk, for specified instances.
static autoPtr< lumpedPointIOMovement > New(const objectRegistry &obr, label ownerId=-1)
Create a movement object in the registry by reading system dictionary.
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
Definition: argList.C:351
messageStream Info
Information stream (stdout output on master, null elsewhere)
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
bool readIfPresent(const word &optName, T &val) const
Read a value from the named option if present.
Definition: argListI.H:316
Foam::argList args(argc, argv)
label setInterpolators(const pointVectorField &pvf, const pointField &points0)
Return the patch-ids associated with a "lumpedPointDisplacement" type.
A primitive field of type <T> with automated input and output.
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:171
The state of lumped points corresponds to positions and rotations.
Namespace for OpenFOAM.
bool append(const fileNameInstant &inst)
Append the specified file instant.