Skip to content

Commit f53b64f

Browse files
feat(core)!: Less flexible but fast extensible state variables
1 parent ef48e40 commit f53b64f

24 files changed

+605
-1579
lines changed

source/Body.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -472,14 +472,16 @@ Body::setState(XYZQuat pos, vec6 vel)
472472
setDependentStates();
473473
}
474474

475-
std::pair<XYZQuat, vec6>
476-
Body::getStateDeriv()
475+
void
476+
Body::getStateDeriv(InstanceStateVarView drdt)
477477
{
478478
if ((type != FREE) && (type != CPLDPIN)) {
479479
LOGERR << "getStateDeriv called for non-free body" << endl;
480480
throw moordyn::invalid_value_error("Invalid body type");
481481
}
482482

483+
XYZQuat u7;
484+
483485
// Get contributions from attached points (and lines attached to
484486
// them) and store in FNet:
485487
doRHS();
@@ -488,10 +490,10 @@ Body::getStateDeriv()
488490
a6 = solveMat6(M, F6net);
489491

490492
// NOTE; is the above still valid even though it includes rotational DOFs?
491-
dPos.pos = v6.head<3>();
493+
u7.pos = v6.head<3>();
492494
// this assumes that the angular velocity is about the global coordinates
493495
// which is true for bodies
494-
dPos.quat = 0.5 * (quaternion(0.0, v6[3], v6[4], v6[5]) * r7.quat).coeffs();
496+
u7.quat = 0.5 * (quaternion(0.0, v6[3], v6[4], v6[5]) * r7.quat).coeffs();
495497
} else { // Pinned body
496498

497499
// account for moment in response to acceleration due to inertial coupling (off-diagonal sub-matrix terms)
@@ -504,10 +506,12 @@ Body::getStateDeriv()
504506
a6(Eigen::seqN(3, 3)) = M_out3.inverse() * Fnet_out3;
505507

506508
// dxdt = V (velocities)
507-
dPos.pos = vec::Zero();
508-
dPos.quat = 0.5 * (quaternion(0.0, v6[3], v6[4], v6[5]) * r7.quat).coeffs();
509+
u7.pos = vec::Zero();
510+
u7.quat = 0.5 * (quaternion(0.0, v6[3], v6[4], v6[5]) * r7.quat).coeffs();
509511
}
510-
return std::make_pair(dPos, a6);
512+
513+
drdt.row(0).head<7>() = u7.toVec7();
514+
drdt.row(0).tail<6>() = a6;
511515
};
512516

513517
const vec6

source/Body.hpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,6 @@ class DECLDIR Body final : public Instance, public SuperCFL
123123
// vec6 r6;
124124
/// body 6dof velocity[x/y/z]
125125
vec6 v6;
126-
/// body quaternion position derivative
127-
XYZQuat dPos;
128126
/// body 6dof acceleration[x/y/z]
129127
vec6 a6;
130128

@@ -379,9 +377,9 @@ class DECLDIR Body final : public Instance, public SuperCFL
379377
*/
380378
void setState(XYZQuat r, vec6 rd);
381379

382-
inline void setState(vec7 r, vec6 rd)
380+
inline void setState(const InstanceStateVarView r)
383381
{
384-
setState(XYZQuat::fromVec7(r), rd);
382+
setState(XYZQuat::fromVec7(r.row(0).head<7>()), r.row(0).tail<6>());
385383
}
386384
/**
387385
* @}
@@ -390,12 +388,12 @@ class DECLDIR Body final : public Instance, public SuperCFL
390388
/** @brief calculate the forces and state derivatives of the body
391389
*
392390
* This function is only meant for free bodies
393-
* @return The states derivatives, i.e. the velocity (first) and the
394-
* acceleration (second)
391+
* @param drdt The states derivatives, i.e. the velocity and the
392+
* acceleration
395393
* @throw moordyn::invalid_value_error If the body is of type
396394
* moordyn::Body::FREE
397395
*/
398-
std::pair<XYZQuat, vec6> getStateDeriv();
396+
void getStateDeriv(InstanceStateVarView drdt);
399397

400398
/** @brief calculates the forces on the body
401399
* @throw moordyn::invalid_value_error If the body is of type
@@ -405,6 +403,18 @@ class DECLDIR Body final : public Instance, public SuperCFL
405403

406404
void Output(real time);
407405

406+
/** @brief Get the number of state variables required by this instance
407+
* @return 1
408+
*/
409+
inline const size_t stateN() const { return 1; }
410+
411+
/** @brief Get the dimension of the state variable
412+
* @return 7 components for position quaternion and 6 components for
413+
* linear and angular velocities, i.e. 13 components
414+
* @warning This function shall be called after ::setup()
415+
*/
416+
inline const size_t stateDims() const { return 13; }
417+
408418
/** @brief Produce the packed data to be saved
409419
*
410420
* The produced data can be used afterwards to restore the saved information

source/IO.cpp

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -398,18 +398,6 @@ IO::Serialize(const XYZQuat& m)
398398
return data;
399399
}
400400

401-
std::vector<uint64_t>
402-
IO::Serialize(const list& m)
403-
{
404-
std::vector<uint64_t> data;
405-
const uint64_t n = m.rows();
406-
data.reserve(1 + n);
407-
data.push_back(Serialize(n));
408-
for (uint64_t i = 0; i < n; i++)
409-
data.push_back(Serialize(m(i)));
410-
return data;
411-
}
412-
413401
std::vector<uint64_t>
414402
IO::Serialize(const std::vector<real>& l)
415403
{
@@ -561,21 +549,6 @@ IO::Deserialize(const uint64_t* in, XYZQuat& out)
561549
return remaining;
562550
}
563551

564-
uint64_t*
565-
IO::Deserialize(const uint64_t* in, list& out)
566-
{
567-
uint64_t n;
568-
uint64_t* remaining = Deserialize(in, n);
569-
if (out.rows() != n)
570-
out.resize(n);
571-
for (unsigned int i = 0; i < n; i++) {
572-
real v;
573-
remaining = Deserialize(remaining, v);
574-
out(i) = v;
575-
}
576-
return remaining;
577-
}
578-
579552
uint64_t*
580553
IO::Deserialize(const uint64_t* in, std::vector<real>& out)
581554
{

source/IO.hpp

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,6 @@ class DECLDIR IO : public LogUser
177177
*/
178178
std::vector<uint64_t> Serialize(const XYZQuat& m);
179179

180-
/** @brief Pack a list to make it writable
181-
* @param m The list
182-
* @return The packed list
183-
*/
184-
std::vector<uint64_t> Serialize(const list& m);
185-
186180
/** @brief Pack a list of floating point numbers to make it writable
187181
* @param l The list
188182
* @return The packed list
@@ -213,23 +207,25 @@ class DECLDIR IO : public LogUser
213207
*/
214208
std::vector<uint64_t> Serialize(const std::vector<mat6>& l);
215209

216-
/** @brief Pack an arbitrarily large vector
217-
* @param l The list
210+
/** @brief Pack an arbitrarily large matrix
211+
* @param l The matrix
218212
* @return The packed list
219213
*/
220-
template<typename T>
221214
inline std::vector<uint64_t> Serialize(
222-
const Eigen::Matrix<T, Eigen::Dynamic, 1>& l)
215+
const Eigen::Matrix<real, Eigen::Dynamic, Eigen::Dynamic>& l)
223216
{
224217
std::vector<uint64_t> data;
225218
const uint64_t n = l.rows();
219+
const uint64_t m = l.cols();
220+
data.reserve(2 + n * m);
226221
data.push_back(Serialize(n));
222+
data.push_back(Serialize(m));
227223
for (uint64_t i = 0; i < n; i++) {
228-
std::vector<uint64_t> subdata = Serialize(l(i));
229-
data.insert(data.end(), subdata.begin(), subdata.end());
224+
for (uint64_t j = 0; j < m; j++) {
225+
data.push_back(Serialize(l(i, j)));
226+
}
230227
}
231228
return data;
232-
233229
}
234230

235231
/** @brief Pack a list of lists to make it writable
@@ -313,13 +309,6 @@ class DECLDIR IO : public LogUser
313309
*/
314310
uint64_t* Deserialize(const uint64_t* in, XYZQuat& out);
315311

316-
/** @brief Unpack a loaded list
317-
* @param in The pointer to the next unread value
318-
* @param out The unpacked value
319-
* @return The new pointer to the remaining data to be read
320-
*/
321-
uint64_t* Deserialize(const uint64_t* in, list& out);
322-
323312
/** @brief Unpack a loaded list of floating point numbers
324313
* @param in The pointer to the next unread value
325314
* @param out The unpacked value
@@ -355,21 +344,25 @@ class DECLDIR IO : public LogUser
355344
*/
356345
uint64_t* Deserialize(const uint64_t* in, std::vector<mat6>& out);
357346

358-
/** @brief Unpack an arbitrarily large vector
347+
/** @brief Unpack an arbitrarily large matrix
359348
* @param in The pointer to the next unread value
360349
* @param out The unpacked vector
361350
* @return The new pointer to the remaining data to be read
362351
*/
363-
template<typename Type>
364-
uint64_t* Deserialize(const uint64_t* in,
365-
Eigen::Matrix<Type, Eigen::Dynamic, 1>& out)
352+
uint64_t* Deserialize(
353+
const uint64_t* in,
354+
Eigen::Matrix<real, Eigen::Dynamic, Eigen::Dynamic>& out)
366355
{
367-
uint64_t n;
368-
uint64_t* remaining = Deserialize(in, n);
369-
if (out.rows() != n)
370-
out.resize(n);
356+
uint64_t* remaining;
357+
uint64_t n, m;
358+
remaining = Deserialize(in, n);
359+
remaining = Deserialize(remaining, m);
360+
if ((out.rows() != n) || (out.cols() != m))
361+
out.resize(n, m);
371362
for (unsigned int i = 0; i < n; i++) {
372-
remaining = Deserialize(remaining, out(i));
363+
for (unsigned int j = 0; j < m; j++) {
364+
remaining = Deserialize(remaining, out(i, j));
365+
}
373366
}
374367
return remaining;
375368
}

source/Instance.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,9 @@ Instance::Instance(moordyn::Log* log)
2828
_id = __instances_counter++;
2929
}
3030

31+
void reset_instance_ids()
32+
{
33+
__instances_counter = 0;
34+
}
35+
3136
} // ::moordyn

source/Instance.hpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
#pragma once
3737

38+
#include "Misc.hpp"
3839
#include "IO.hpp"
3940
#include "Log.hpp"
4041
#include <utility>
@@ -67,26 +68,45 @@ class DECLDIR Instance : public io::IO
6768
* The unique identifier is a growing index which identifies every single
6869
* created instance. Even if an instance is removed, the index will remain
6970
* taken.
71+
* That applies even for multiple instances generation.
7072
* @return The unique identifier
73+
* @warning It cannot be assumed that the first taken index will be 0
74+
* @warning It cannot be assumed that consequtive ids will be assigned
7175
*/
72-
inline const size_t Id() const { return _id; }
76+
inline const size_t id() const { return _id; }
77+
78+
/** @brief Set the state
79+
* @param r The state variable
80+
*/
81+
virtual void setState(const InstanceStateVarView r) = 0;
82+
83+
/** @brief Calculate forces and get the derivative of the states
84+
* @param drdt Output state derivatives
85+
* @throws nan_error If nan values are detected in any node position
86+
*/
87+
virtual void getStateDeriv(InstanceStateVarView drdt) = 0;
7388

7489
/** @brief Get the number of state variables required by this instance
7590
*
7691
* This can be seen as the number of rows on the state variables holder.
7792
* @return The number of state variables
7893
*/
79-
virtual inline const size_t state_n() const { return 1; }
94+
virtual inline const size_t stateN() const { return 1; }
8095

8196
/** @brief Get the dimension of the state variable.
8297
*
8398
* This can be seen as the number of columns on the state variables holder.
8499
* @return The dimension of the state variable
85100
*/
86-
virtual inline const size_t state_dims() const { return 6; }
101+
virtual inline const size_t stateDims() const { return 6; }
87102
private:
88103
/// Unique identifier of this instance
89104
size_t _id;
90105
};
91106

107+
/** @brief Reset the instances Ids, so they will be assigned again starting
108+
* from 0
109+
*/
110+
void reset_instance_ids();
111+
92112
} // ::moordyn

source/Line.cpp

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -679,21 +679,11 @@ Line::setState(const std::vector<vec>& pos, const std::vector<vec>& vel)
679679
}
680680

681681
void
682-
Line::setState(const StateVarRef pos, const StateVarRef vel)
682+
Line::setState(const InstanceStateVarView state)
683683
{
684-
if ((pos.rows() != N - 1) || (vel.rows() != N - 1)) {
685-
LOGERR << "Invalid input size" << endl;
686-
throw moordyn::invalid_value_error("Invalid input size");
687-
}
688684
for (unsigned int i = 1; i < N; i++) {
689-
if ((pos(i - 1).rows() != 3) || (vel(i - 1).rows() != 3)) {
690-
LOGERR << "Invalid point input size on line " << number
691-
<< " node " << i << ". pos size is " << pos(i - 1).rows()
692-
<< " and vel size is " << vel(i - 1).rows() << endl;
693-
throw moordyn::invalid_value_error("Invalid input size");
694-
}
695-
r[i] = pos(i - 1);
696-
rd[i] = vel(i - 1);
685+
r[i] = state.row(i - 1).head<3>();
686+
rd[i] = state.row(i - 1).segment<3>(3);
697687
}
698688
}
699689

@@ -787,7 +777,7 @@ Line::getEndSegmentMoment(EndPoints end_point, EndPoints rod_end_point) const
787777
}
788778

789779
void
790-
Line::getStateDeriv(StateVarRef vel, StateVarRef acc)
780+
Line::getStateDeriv(InstanceStateVarView drdt)
791781
{
792782
// NOTE:
793783
// Jose Luis Cercos-Pita: This is by far the most consuming function of the
@@ -1200,8 +1190,8 @@ Line::getStateDeriv(StateVarRef vel, StateVarRef acc)
12001190
// For small systems it is usually faster to compute the inverse
12011191
// of the matrix. See
12021192
// https://eigen.tuxfamily.org/dox/group__TutorialLinearAlgebra.html
1203-
acc(i - 1) = M[i].inverse() * Fnet[i];
1204-
vel(i - 1) = rd[i];
1193+
drdt.row(i - 1).head<3>() = rd[i];
1194+
drdt.row(i - 1).segment<3>(3) = M[i].inverse() * Fnet[i];
12051195
}
12061196
};
12071197

0 commit comments

Comments
 (0)