pointMasses.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) 2016-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 "pointMasses.H"
27 #include "TableReader.H"
28 #include "UIndirectList.H"
29 #include "one.H"
31 
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 namespace RBD
37 {
40 }
41 }
42 
43 
44 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
45 
46 template<class Type, class Op>
47 Foam::tmp<Foam::Field<Type>> Foam::RBD::pointMasses::sectionMuNs
48 (
49  const direction axis,
50  const scalarField& distances,
51  const Op& op
52 ) const
53 {
54  tmp<Field<Type>> tResult
55  (
56  new Field<Type>(distances.size() - 1, pTraits<Type>::zero)
57  );
58  Field<Type>& result = tResult.ref();
59 
60  if (!sortedPointis_.set(axis))
61  {
62  sortedPointis_.set(axis, new labelList(points_.size()));
63 
65  (
66  points_,
67  sortedPointis_[axis],
68  [this, axis](const label a, const label b)
69  {
70  return points_[a][axis] < points_[b][axis];
71  }
72  );
73  }
74 
75  const UIndirectList<point> sortedPoints(points_, sortedPointis_[axis]);
76  const UIndirectList<scalar> sortedMasses(masses_, sortedPointis_[axis]);
77 
78  label sortedPointi = 0, sectioni = 0;
79 
80  while
81  (
82  sortedPointi < sortedPoints.size()
83  && sortedPoints[sortedPointi][axis] < distances[0]
84  ) sortedPointi ++;
85 
86  for (; sortedPointi < sortedPoints.size(); ++ sortedPointi)
87  {
88  while
89  (
90  sectioni < result.size()
91  && sortedPoints[sortedPointi][axis] > distances[sectioni + 1]
92  ) sectioni ++;
93 
94  if (sectioni >= result.size()) break;
95 
96  result[sectioni] +=
97  op(sortedPoints[sortedPointi])*sortedMasses[sortedPointi];
98  }
99 
100  return tResult;
101 }
102 
103 
104 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
105 
107 (
108  const word& name,
109  const dictionary& dict
110 )
111 :
113  reader_
114  (
115  dict.isDict("pointMasses")
116  ? TableReader<point, scalar>::New
117  (
118  "pointMasses",
119  {dimLength, dimMass},
120  dict.subDict("pointMasses")
121  ).ptr()
122  : nullptr
123  ),
124  points_(),
125  masses_(),
126  sortedPointis_(3)
127 {
128  // Read the point masses
129  const List<Tuple2<point, scalar>> pointsAndMasses =
130  reader_.valid()
131  ? reader_->read
132  (
133  {dimLength, dimMass},
134  dict.subDict("pointMasses")
135  )
137  (
138  {dimLength, dimMass},
139  dict,
140  "pointMasses"
141  );
142  points_.resize(pointsAndMasses.size());
143  masses_.resize(pointsAndMasses.size());
144  forAll(pointsAndMasses, i)
145  {
146  points_[i] = pointsAndMasses[i].first();
147  masses_[i] = pointsAndMasses[i].second();
148  }
149 
150  if (points_.size() < 4)
151  {
153  << "A " << typeName << " body requires at least four point masses"
154  << exit(FatalIOError);
155  }
156 
157  // Calculate the mass, the centre of mass, and the inertia tensor about the
158  // centre of mass
159  const scalar m = sum(masses_);
160  const point c = sum(points_*masses_)/m;
161  const pointField r(points_ - c);
162  const symmTensor Ic = sum((symmTensor::I*(r & r) - sqr(r))*masses_);
163  const scalar detIc = det(Ic);
164 
165  if (detIc < rootVSmall || detIc < rootSmall*pow3(mag(Ic)))
166  {
168  << "The inertia tensor of the " << typeName << " body '" << name
169  << "' is singular. Ensure the point masses are not co-planar or"
170  << " co-linear." << exit(FatalIOError);
171  }
172 
173  rigidBodyInertia::operator=(rigidBodyInertia(m, c, Ic));
174 }
175 
176 
178 :
179  rigidBody(pm),
180  reader_(pm.reader_, false),
181  points_(pm.points_),
182  masses_(pm.masses_),
183  sortedPointis_(3)
184 {}
185 
186 
188 {
189  return autoPtr<rigidBody>(new pointMasses(*this));
190 }
191 
192 
193 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
194 
196 {}
197 
198 
199 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
200 
202 (
203  const direction axis,
204  const scalarField& distances
205 ) const
206 {
207  return
208  sectionMuNs<scalar>
209  (
210  axis,
211  distances,
212  [](const point&) { return one(); }
213  );
214 }
215 
216 
218 (
219  const direction axis,
220  const scalarField& distances
221 ) const
222 {
223  return
224  sectionMuNs<vector>
225  (
226  axis,
227  distances,
228  [](const point& p) { return p; }
229  );
230 }
231 
232 
234 (
235  const direction axis,
236  const scalarField& distances
237 ) const
238 {
239  return
240  sectionMuNs<symmTensor>
241  (
242  axis,
243  distances,
244  [](const point& p) { return sqr(p); }
245  );
246 }
247 
248 
250 {
251  writeEntry(os, "type", type());
252 
253  // Write the point masses. Bit of a palarver to get the formatting right.
254  List<Tuple2<point, scalar>> pointsAndMasses(points_.size());
255  forAll(pointsAndMasses, i)
256  {
257  pointsAndMasses[i].first() = points_[i];
258  pointsAndMasses[i].second() = masses_[i];
259  }
260  if (reader_.valid())
261  {
262  os << indent << "pointMasses" << endl
264  << incrIndent;
265  reader_->write(os, {dimLength, dimMass}, pointsAndMasses);
266  os << decrIndent
267  << indent << token::END_BLOCK << endl;
268  }
269  else
270  {
272  (
273  os,
274  {dimLength, dimMass},
275  pointsAndMasses,
276  "pointMasses"
277  );
278  }
279 }
280 
281 
282 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Macros for easy insertion into run-time selection tables.
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
void resize(const label)
Alias for setSize(const label)
Definition: ListI.H:138
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
virtual Ostream & write(const token &)
Write token.
Definition: Ostream.C:51
Specialisation of rigidBody to construct a pointMasses given the mass and lengths of the sides.
Definition: pointMasses.H:57
virtual tmp< vectorField > sectionMu1s(const direction axis, const scalarField &distances) const
Return the first moments of the sections of the body between.
Definition: pointMasses.C:218
virtual void write(Ostream &) const
Write.
Definition: pointMasses.C:249
virtual tmp< symmTensorField > sectionMu2s(const direction axis, const scalarField &distances) const
Return the second moments of the sections of the body between.
Definition: pointMasses.C:234
virtual autoPtr< rigidBody > clone() const
Return clone of this pointMasses.
Definition: pointMasses.C:187
pointMasses(const word &name, const dictionary &dict)
Construct from dictionary.
Definition: pointMasses.C:107
virtual tmp< scalarField > sectionMu0s(const direction axis, const scalarField &distances) const
Return the zeroth moments of the sections of the body between.
Definition: pointMasses.C:202
virtual ~pointMasses()
Destructor.
Definition: pointMasses.C:195
This class represents the linear and angular inertia of a rigid body by the mass, centre of mass and ...
const vector & c() const
Return the centre of mass of the rigid-body.
rigidBodyInertia()
Null constructor, initialises to zero.
scalar m() const
Return the mass of the rigid-body.
const symmTensor & Ic() const
Return the inertia tensor of the rigid-body about the centre of mass.
const word & name() const
Return name.
Definition: rigidBodyI.H:65
static const SymmTensor I
Definition: SymmTensor.H:72
Base class to read table data for tables.
Definition: TableReader.H:51
Reads an interpolation table from the values entry in OpenFOAM-format.
virtual List< Tuple2< Coordinate, Value > > read(const Function1s::unitSets &units, const dictionary &dict, const word &valuesKeyword="values") const
Read values.
virtual void write(Ostream &os, const Function1s::unitSets &units, const List< Tuple2< Coordinate, Value >> &table, const word &valuesKeyword="values") const
Write settings and values.
A List with indirect addressing.
Definition: UIndirectList.H:61
label size() const
Return the number of elements in the list.
T & first()
Return the first element of the list.
Definition: UListI.H:114
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
A class representing the concept of 1 (scalar(1)) used to avoid unnecessary manipulations for objects...
Definition: one.H:51
Traits class for primitives.
Definition: pTraits.H:53
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
@ BEGIN_BLOCK
Definition: token.H:114
@ END_BLOCK
Definition: token.H:115
Template function which returns the un-mangled name of a given type. Useful for types which do not ha...
A class for handling words, derived from string.
Definition: word.H:63
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
volScalarField & b
Definition: createFields.H:27
addToRunTimeSelectionTable(rigidBody, cuboid, dictionary)
defineTypeNameAndDebug(cuboid, 0)
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:272
List< label > labelList
A List of labels.
Definition: labelList.H:56
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
const dimensionSet & dimMass
Definition: dimensions.C:140
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
const dimensionSet & dimLength
Definition: dimensions.C:141
SymmTensor< scalar > symmTensor
SymmTensor of scalars.
Definition: symmTensor.H:48
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:265
vector point
Point is a vector.
Definition: point.H:41
tmp< DimensionedField< typename outerProduct< Type, Type >::type, GeoMesh, Field >> sqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
void pow3(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
IOerror FatalIOError
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
void det(pointPatchField< scalar > &, const pointPatchField< tensor > &)
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
void sortedOrder(const UList< T > &, labelList &order)
Generate the (stable) sort order for the list.
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:243
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
void writeEntry(Ostream &os, const word &key, const DimensionedFieldFunction< DimensionedFieldType > &f)
uint8_t direction
Definition: direction.H:45
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
#define Op(opName, op)
Definition: ops.H:100
dictionary dict
volScalarField & p