1 /* 2 * MBDyn (C) is a multibody analysis code. 3 * http://www.mbdyn.org 4 * 5 * Copyright (C) 1996-2017 6 * 7 * Pierangelo Masarati <masarati@aero.polimi.it> 8 * Paolo Mantegazza <mantegazza@aero.polimi.it> 9 * 10 * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano 11 * via La Masa, 34 - 20156 Milano, Italy 12 * http://www.aero.polimi.it 13 * 14 * Changing this copyright notice is forbidden. 15 * 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License as published by 18 * the Free Software Foundation (version 2 of the License). 19 * 20 * 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program; if not, write to the Free Software 28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 29 */ 30 31 /* 32 * NOTE: this is intentionally configuration-independent. 33 */ 34 35 #ifndef MBC_H 36 #define MBC_H 37 38 #ifdef __cplusplus 39 extern "C" { 40 #endif /* __cplusplus */ 41 42 #include <stdint.h> 43 44 /** \brief Legal commands 45 * 46 * The values of this enumeration appear as tags at the beginning 47 * of each communication. 48 */ 49 enum ESCmd { 50 ES_UNKNOWN = -1, 51 /* 1 intentionally unused */ 52 ES_REGULAR_DATA = 2, 53 /* 3 intentionally unused */ 54 ES_GOTO_NEXT_STEP = 4, 55 ES_ABORT = 5, 56 ES_REGULAR_DATA_AND_GOTO_NEXT_STEP = 6, 57 ES_NEGOTIATION = 7, 58 ES_OK = 8, 59 60 ES_LAST 61 }; 62 63 /** \brief Parameters used to control the communication type and fields. */ 64 enum MBCType { 65 MBC_MODAL = 0x0001U, 66 MBC_NODAL = 0x0002U, 67 MBC_MODAL_NODAL_MASK = (MBC_MODAL | MBC_NODAL), 68 69 MBC_REF_NODE = 0x0004U, 70 71 MBC_ACCELS = 0x0008U, 72 73 MBC_LABELS = 0x0010U, 74 75 /** Regular nodes orientation: orientation vector */ 76 MBC_ROT_THETA = 0x0100U, 77 /** Regular nodes orientation: orientation matrix */ 78 MBC_ROT_MAT = 0x0200U, 79 /** Regular nodes orientation: Euler angles (123 sequence) */ 80 MBC_ROT_EULER_123 = 0x0400U, 81 82 /* add more? */ 83 84 /** Regular nodes orientation: suppress orientation 85 * (also suppresses angular velocities and moments) */ 86 MBC_ROT_NONE = 0x0000U, 87 88 MBC_ROT_MASK = (MBC_ROT_THETA | MBC_ROT_MAT | MBC_ROT_EULER_123), 89 90 /** Reference node orientation: orientation vector */ 91 MBC_REF_NODE_ROT_THETA = (MBC_ROT_THETA << 4), 92 /** Reference node orientation: orientation matrix */ 93 MBC_REF_NODE_ROT_MAT = (MBC_ROT_MAT << 4), 94 /** Reference node orientation: Euler angles (123 sequence) */ 95 MBC_REF_NODE_ROT_EULER_123 = (MBC_ROT_EULER_123 << 4), 96 97 MBC_REF_NODE_ROT_MASK = (MBC_ROT_MASK << 4), 98 99 MBC_LAST 100 }; 101 102 /** \brief Connection data structure (partially opaque) */ 103 typedef struct { 104 /** Opaque. */ 105 int sock; 106 107 /** Opaque. */ 108 unsigned sock_flags; 109 110 /** Opaque. */ 111 int recv_flags; 112 113 /** Opaque. */ 114 int send_flags; 115 116 /** Opaque. */ 117 uint8_t cmd; 118 119 /** Flag that modifies response behavior: 120 * - when 0, on convergence send(2) passes ES_GOTO_NEXT_STEP (convergence); 121 * - when 1, on convergence send(2) passes ES_REGULAR_DATA_AND_GOTO_NEXT_STEP (convergence along with last set of new data). 122 * 123 * In most cases, should be set to 1. 124 */ 125 char data_and_next; 126 127 /** Verbose on stdout */ 128 int verbose; 129 130 /** Connect(2) timeout. When peer is not listening: 131 * - a value of 0 results in immediate return with error; 132 * - a positive value corresponds to a timeout in seconds; 133 * - a negative value corresponds to never timing out. 134 * 135 * During timeout, connect(2) is periodically retried. 136 */ 137 int timeout; 138 } mbc_t; 139 140 /** \brief Opaque. */ 141 /* validate command 142 * 143 * command needs to be set in mbc->cmd 144 */ 145 extern int 146 mbc_check_cmd(mbc_t *mbc); 147 148 /** \brief Opaque. */ 149 /* get command from peer 150 * 151 * command is stored in mbc->cmd 152 */ 153 extern int 154 mbc_get_cmd(mbc_t *mbc); 155 156 /** \brief Opaque. */ 157 /* put command to peer 158 * 159 * command needs to be set in mbc->cmd 160 */ 161 extern int 162 mbc_put_cmd(mbc_t *mbc); 163 164 /** \brief Initialize communication using "inet" socket. 165 * 166 * \param [in,out] mbc a pointer to a valid mbc_t structure 167 * \param [in] host hostname 168 * \param [in] port port number 169 * 170 * Connects to peer "inet" socket using hostname and port number; 171 * host and port must be defined. If peer is not listening, 172 * the behavior depends on mbc_t::timeout. 173 * 174 * @return 0 on success, !0 on failure. 175 */ 176 extern int 177 mbc_inet_init(mbc_t *mbc, const char *host, short unsigned port); 178 179 /** \brief Initialize communication using "unix" socket. 180 * 181 * \param [in,out] mbc a pointer to a valid mbc_t structure 182 * \param [in] path pathname 183 * 184 * Connects to peer "unix" socket using pathname; 185 * path must be defined. If peer is not listening, 186 * the behavior depends on mbc::timeout. 187 * 188 * @return 0 on success, !0 on failure. 189 */ 190 extern int 191 mbc_unix_init(mbc_t *mbc, const char *path); 192 193 /** 194 * \brief Reference node (AKA "rigid") stuff (partially opaque). 195 * 196 * Users do not need to access members directly; 197 * macros documented in the following should be used instead. 198 * 199 * Flags: 200 * - MBC_F_REF_NODE(mbc): true when reference node is defined 201 * - MBC_F_LABELS(mbc): true when labels communication is enabled 202 * - MBC_F_ACCELS(mbc): true when accelerations communication is enabled 203 * - MBC_F_ROT(mbc): orientation mode (see MBC_ROT_* in ::MBCType) 204 * - MBC_F_ROT_THETA(mbc): true when orientation mode is orientation vector 205 * - MBC_F_ROT_MAT(mbc): true when orientation mode is orientation matrix 206 * - MBC_F_ROT_EULER_123(mbc): true when orientation mode is Euler angles (123 sequence) 207 * - MBC_F_ROT_REF_NODE(mbc): orientation mode of reference node (see MBC_ROT_* in ::MBCType; MBC_F_REF_NODE(mbc) must be true) 208 * 209 * Fields (MBC_F_REF_NODE(mbc) must be true): 210 * - MBC_R_K_LABEL(mbc): returns the (uint32_t) label of the reference node (MBC_F_LABELS(mbc) must be true) 211 * - MBC_R_X(mbc): returns a (double *) pointer to the three components of reference node position 212 * - MBC_R_THETA(mbc): returns a (double *) pointer to the three components of the reference node orientation vector 213 * (MBC_F_ROT_THETA(mbc) must be true) 214 * - MBC_R_R(mbc): returns a (double *) pointer to the nine components of the reference node orientation matrix, 215 * column-major (Fortran style; MBC_F_ROT_MAT(mbc) must be true) 216 * - MBC_R_EULER_123(mbc): returns a (double *) pointer to the three components of the reference node Euler angles 217 * (123 sequence; MBC_F_ROT_EULER_123(mbc) must be true) 218 * - MBC_R_XP(mbc): returns a (double *) pointer to the three components of reference node velocity 219 * - MBC_R_OMEGA(mbc): returns a (double *) pointer to the three components of reference node angular velocity 220 * - MBC_R_XPP(mbc): returns a (double *) pointer to the three components of reference node acceleration 221 * (MBC_F_ACCELS(mbc) must be true) 222 * - MBC_R_OMEGAP(mbc): returns a (double *) pointer to the three components of reference node angular acceleration 223 * (MBC_F_ACCELS(mbc) must be true) 224 * - MBC_R_D_LABEL(mbc): the (uint32_t) label of the reference node (in the output buffer; MBC_F_LABELS(mbc) must be true) 225 * - MBC_R_F(mbc): returns a (double *) pointer to the three components of reference node force 226 * - MBC_R_M(mbc): returns a (double *) pointer to the three components of reference node moment 227 * - MBC_R_KINEMATICS_SIZE(mbc): returns the size of the input buffer 228 * - MBC_R_DYNAMICS_SIZE(mbc): returns the size of the output buffer 229 * - MBC_R_SIZE(mbc): returns the cumulative size of the buffers 230 * - MBC_R_KINEMATICS(mbc): returns a (void *) pointer to the input buffer 231 * - MBC_R_DYNAMICS(mbc): returns a (void *) pointer to the output buffer 232 */ 233 typedef struct { 234 uint32_t flags; 235 #define MBC_F(mbc) ((mbc)->mbcr.flags) 236 #define MBC_F_GET(mbc, f) (MBC_F(mbc) & (f)) 237 #define MBC_F_SET(mbc, f) (MBC_F(mbc) |= (f)) 238 #define MBC_F_RESET(mbc, f) (MBC_F(mbc) &= ~(f)) 239 240 #define MBC_F_REF_NODE(mbc) MBC_F_GET(mbc, MBC_REF_NODE) 241 #define MBC_F_LABELS(mbc) MBC_F_GET(mbc, MBC_LABELS) 242 #define MBC_F_ACCELS(mbc) MBC_F_GET(mbc, MBC_ACCELS) 243 #define MBC_F_ROT(mbc) MBC_F_GET(mbc, MBC_ROT_MASK) 244 #define MBC_F_ROT_THETA(mbc) MBC_F_GET(mbc, MBC_ROT_THETA) 245 #define MBC_F_ROT_MAT(mbc) MBC_F_GET(mbc, MBC_ROT_MAT) 246 #define MBC_F_ROT_EULER_123(mbc) MBC_F_GET(mbc, MBC_ROT_EULER_123) 247 #define MBC_U_REF_NODE_ROT_2_ROT(u) (((u) & MBC_REF_NODE_ROT_MASK) >> 4) 248 #define MBC_U_ROT_2_REF_NODE_ROT(u) (((u) & MBC_ROT_MASK) << 4) 249 #define MBC_F_ROT_REF_NODE(mbc) MBC_U_REF_NODE_ROT_2_ROT(MBC_F_GET((mbc), MBC_REF_NODE_ROT_MASK)) 250 #define MBC_F_REF_NODE_ROT(mbc) MBC_F_GET(mbc, MBC_REF_NODE_ROT_MASK) 251 252 #define MBC_F_SET_REF_NODE(mbc) MBC_F_SET(mbc, MBC_REF_NODE) 253 #define MBC_F_SET_LABELS(mbc) MBC_F_SET(mbc, MBC_LABELS) 254 #define MBC_F_SET_ACCELS(mbc) MBC_F_SET(mbc, MBC_ACCELS) 255 #define MBC_F_SET_ROT_THETA(mbc) MBC_F_SET(mbc, MBC_ROT_THETA) 256 #define MBC_F_SET_ROT_MAT(mbc) MBC_F_SET(mbc, MBC_ROT_MAT) 257 #define MBC_F_SET_ROT_EULER_123(mbc) MBC_F_SET(mbc, MBC_ROT_EULER_123) 258 259 /* reference node data */ 260 union { 261 /* NOTE: wasting an uint32_t for each uint32_t to make sure alignment is on double */ 262 char char_r_ptr[(2 + 2) * sizeof(uint32_t) + (3 + 9 + 3 + 3 + 3 + 3 + 3 + 3) * sizeof(double)]; 263 uint32_t uint32_t_r_ptr[(2 + 2) + (3 + 9 + 3 + 3 + 3 + 3 + 3 + 3) * sizeof(double) / sizeof(uint32_t)]; 264 double double_r_ptr[(2 + 2) * sizeof(uint32_t) / sizeof(double) + (3 + 9 + 3 + 3 + 3 + 3 + 3 + 3) * sizeof(double)]; 265 } r_ptr; 266 267 uint32_t k_size; 268 int32_t r_k_label; 269 int32_t r_k_x; 270 int32_t r_k_theta; 271 int32_t r_k_r; 272 int32_t r_k_euler_123; 273 int32_t r_k_xp; 274 int32_t r_k_omega; 275 int32_t r_k_xpp; 276 int32_t r_k_omegap; 277 uint32_t d_size; 278 int32_t r_d_label; 279 int32_t r_d_f; 280 int32_t r_d_m; 281 #define MBC_R_PTR(mbc, type, off) ((off) < 0 ? NULL : ((type *)&((mbc)->mbcr.r_ptr.type ## _r_ptr[(off)]))) 282 #define MBC_R_K_LABEL(mbc) (MBC_R_PTR((mbc), uint32_t, (mbc)->mbcr.r_k_label)[0]) 283 #define MBC_R_X(mbc) (MBC_R_PTR((mbc), double, (mbc)->mbcr.r_k_x)) 284 #define MBC_R_THETA(mbc) (MBC_R_PTR((mbc), double, (mbc)->mbcr.r_k_theta)) 285 #define MBC_R_R(mbc) (MBC_R_PTR((mbc), double, (mbc)->mbcr.r_k_r)) 286 #define MBC_R_EULER_123(mbc) (MBC_R_PTR((mbc), double, (mbc)->mbcr.r_k_euler_123)) 287 #define MBC_R_XP(mbc) (MBC_R_PTR((mbc), double, (mbc)->mbcr.r_k_xp)) 288 #define MBC_R_OMEGA(mbc) (MBC_R_PTR((mbc), double, (mbc)->mbcr.r_k_omega)) 289 #define MBC_R_XPP(mbc) (MBC_R_PTR((mbc), double, (mbc)->mbcr.r_k_xpp)) 290 #define MBC_R_OMEGAP(mbc) (MBC_R_PTR((mbc), double, (mbc)->mbcr.r_k_omegap)) 291 #define MBC_R_D_LABEL(mbc) (MBC_R_PTR((mbc), uint32_t, (mbc)->mbcr.r_d_label)[0]) 292 #define MBC_R_F(mbc) (MBC_R_PTR((mbc), double, (mbc)->mbcr.r_d_f)) 293 #define MBC_R_M(mbc) (MBC_R_PTR((mbc), double, (mbc)->mbcr.r_d_m)) 294 #define MBC_R_KINEMATICS_SIZE(mbc) ((mbc)->mbcr.k_size) 295 #define MBC_R_DYNAMICS_SIZE(mbc) ((mbc)->mbcr.d_size) 296 #define MBC_R_SIZE(mbc) (MBC_R_KINEMATICS_SIZE(mbc) + MBC_R_DYNAMICS_SIZE(mbc)) 297 #define MBC_R_KINEMATICS(mbc) ((void *)(mbc)->mbcr.r_ptr.char_r_ptr) 298 #define MBC_R_DYNAMICS(mbc) ((void *)(MBC_R_KINEMATICS(mbc) + MBC_R_KINEMATICS_SIZE(mbc))) 299 } mbc_rigid_t; 300 301 /** 302 * \brief Nodal stuff (partially opaque). 303 * 304 * Users do not need to access members directly; 305 * macros documented in the following should be used instead. 306 * 307 * Fields: 308 * - MBC_N_K_LABELS(mbc): returns a (uint32_t *) pointer to input node labels (MBC_F_LABELS(mbc) must be true) 309 * - MBC_N_X(mbc): returns a (double *) pointer to positions of nodes (first node x,y,z; second node x,y,z; ...) 310 * - MBC_N_THETA(mbc): returns a (double *) pointer to orientation vectors of nodes 311 * (first node x,y,z; second node x,y,z; ...; MBC_F_ROT(mbc) must not be ::MBC_ROT_NONE) 312 * - MBC_N_R(mbc): returns a (double *) pointer to orientation vectors of nodes 313 * (first node r11,r21,r31,r12,r22,r32,r13,r23,r33; second node r11,...,r33; ...; 314 * MBC_F_ROT(mbc) must not be ::MBC_ROT_NONE) 315 * - MBC_N_EULER_123(mbc): returns a (double *) pointer to Euler angles of nodes 316 * (first node x,y,z; second node x,y,z; ...; MBC_F_ROT(mbc) must not be ::MBC_ROT_NONE) 317 * - MBC_N_XP(mbc): returns a (double *) pointer to velocities of nodes (first node x,y,z; second node x,y,z; ...) 318 * - MBC_N_OMEGA(mbc): returns a (double *) pointer to angular velocities of nodes 319 * (first node x,y,z; second node x,y,z; ...; MBC_F_ROT(mbc) must not be ::MBC_ROT_NONE) 320 * - MBC_N_XPP(mbc): returns a (double *) pointer to accelerations of nodes 321 * (first node x,y,z; second node x,y,z; ...; MBC_F_ACCELS(mbc) must be true) 322 * - MBC_N_OMEGAP(mbc): returns a (double *) pointer to angular accelerations of nodes 323 * (first node x,y,z; second node x,y,z; ...; MBC_F_ACCELS(mbc) must be true and MBC_F_ROT(mbc) must not be ::MBC_ROT_NONE) 324 * - MBC_N_D_LABELS(mbc): returns a (uint32_t *) pointer to output node labels (MBC_F_LABELS(mbc) must be true) 325 * - MBC_N_F(mbc): returns a (double *) pointer to forces (first node x,y,z; second node x,y,z; ...) 326 * - MBC_N_M(mbc): returns a (double *) pointer to moments (first node x,y,z; second node x,y,z; ...; 327 * MBC_F_ROT(mbc) must not be ::MBC_ROT_NONE) 328 * - MBC_N_KINEMATICS_SIZE(mbc): returns the size of the input buffer 329 * - MBC_N_DYNAMICS_SIZE(mbc): returns the size of the output buffer 330 * - MBC_N_SIZE(mbc): returns the cumulative size of the buffers 331 * - MBC_N_KINEMATICS(mbc): returns a (void *) pointer to the input buffer 332 * - MBC_N_DYNAMICS(mbc): returns a (void *) pointer to the output buffer 333 */ 334 typedef struct { 335 mbc_t mbc; 336 mbc_rigid_t mbcr; 337 338 /* nodal data */ 339 uint32_t nodes; 340 uint32_t k_size; 341 342 char *n_ptr; 343 /* n_k_labels optional */ 344 uint32_t *n_k_labels; 345 double *n_k_x; 346 /* n_k_theta, n_k_r, n_k_euler_123 mutually exclusive */ 347 double *n_k_theta; 348 double *n_k_r; 349 double *n_k_euler_123; 350 double *n_k_xp; 351 double *n_k_omega; 352 /* n_k_xpp, n_k_omegap optional */ 353 double *n_k_xpp; 354 double *n_k_omegap; 355 356 uint32_t d_size; 357 /* n_d_labels optional */ 358 uint32_t *n_d_labels; 359 double *n_d_f; 360 double *n_d_m; 361 362 #define MBC_N_K_LABELS(mbc) ((mbc)->n_k_labels) 363 #define MBC_N_X(mbc) ((mbc)->n_k_x) 364 #define MBC_N_THETA(mbc) ((mbc)->n_k_theta) 365 #define MBC_N_R(mbc) ((mbc)->n_k_r) 366 #define MBC_N_EULER_123(mbc) ((mbc)->n_k_euler_123) 367 #define MBC_N_XP(mbc) ((mbc)->n_k_xp) 368 #define MBC_N_OMEGA(mbc) ((mbc)->n_k_omega) 369 #define MBC_N_XPP(mbc) ((mbc)->n_k_xpp) 370 #define MBC_N_OMEGAP(mbc) ((mbc)->n_k_omegap) 371 #define MBC_N_D_LABELS(mbc) ((mbc)->n_d_labels) 372 #define MBC_N_F(mbc) ((mbc)->n_d_f) 373 #define MBC_N_M(mbc) ((mbc)->n_d_m) 374 #define MBC_N_KINEMATICS_SIZE(mbc) ((mbc)->k_size) 375 #define MBC_N_DYNAMICS_SIZE(mbc) ((mbc)->d_size) 376 #define MBC_N_KINEMATICS(mbc) ((void *)(mbc)->n_ptr) 377 #define MBC_N_DYNAMICS(mbc) ((void *)(MBC_N_KINEMATICS(mbc) + MBC_N_KINEMATICS_SIZE(mbc))) 378 #define MBC_N_SIZE(mbc) (MBC_N_KINEMATICS_SIZE(mbc) + MBC_N_DYNAMICS_SIZE(mbc)) 379 } mbc_nodal_t; 380 381 /** \brief Initialize nodal data. 382 * 383 * \param [in,out] mbc pointer to a valid mbc_nodal_t structure 384 * \param [in] refnode non-zero if reference node is defined 385 * \param [in] nodes number of nodes 386 * \param [in] labels true to enable labels 387 * \param [in] rot orientation type 388 * \param [in] accels true to enable accelerations 389 * 390 * Either reference node motion must be defined (refnode != 0), 391 * or nodes must be > 0, or both. 392 * 393 * if nodes > 0, this function calls malloc(3) to alloc memory 394 * that needs to be freed by calling mbc_nodal_destroy() 395 * 396 * if labels != 0, labels are handled as well 397 * 398 * rot must be one of ::MBCType MBC_ROT_*; 399 * if it is set to ::MBC_ROT_NONE, only positions and forces are handled. 400 * 401 * if accels != 0, accelerations are handled as well. 402 * 403 * @return 0 on success, !0 on failure. 404 */ 405 extern int 406 mbc_nodal_init(mbc_nodal_t *mbc, unsigned refnode, unsigned nodes, 407 unsigned labels, unsigned rot, unsigned accels); 408 409 /** \brief Destroy nodal data. 410 * 411 * \param [in,out] mbc pointer to a valid mbc_nodal_t structure 412 * 413 * NOTE: does NOT free mbc. 414 * 415 * @return 0 on success, !0 on failure. 416 */ 417 extern int 418 mbc_nodal_destroy(mbc_nodal_t *mbc); 419 420 /** \brief Negotiate nodal data. 421 * 422 * \param [in] mbc pointer to a valid mbc_nodal_t structure 423 * 424 * At least reference node motion must be defined 425 * (MBC_F_REF_NODE(mbc) must be true), 426 * or nodes > 0 427 * 428 * The socket must be initialized and connected. 429 * 430 * This function sends a negotiation request to the master. 431 * 432 * @return 0 on success, !0 on failure. 433 */ 434 /* 435 * the protocol consists in: 436 * 437 * - negotiation request: 438 * - the negotiation request tag (ES_NEGOTIATION, uint8_t) 439 * - a bunch of flags (uint32_t), containing: 440 * - the type of interface (MBC_MODAL or MBC_NODAL) 441 * - whether a reference node is defined, MBC_REF_NODE OR-ed to previous 442 * - more... 443 * - the number of nodes (uint32_t) 444 * 445 * - negotiation response: 446 * - the negotiation response tag (ES_OK or ES_ABORT, uint8_t) 447 */ 448 extern int 449 mbc_nodal_negotiate_request(mbc_nodal_t *mbc); 450 451 /** \brief Unused. */ 452 /* 453 * companion of above, provided for completeness; not used 454 */ 455 extern int 456 mbc_nodal_negotiate_response(mbc_nodal_t *mbc); 457 458 /** \brief Get nodal motion from peer. 459 * 460 * \param [in,out] pointer to a valid mbc_nodal_t structure 461 * 462 * After the call to this function succeeds: 463 * - if MBC_F_REF_NODE(mbc) is true, reference node motion can be accessed using macros MBC_R_X(mbc) and similar; 464 * - if mbc_nodal_t::nodes > 0, nodal motion can be accessed using macros MBC_N_X(mbc) and similar. 465 * 466 * @return 0 on success, !0 on failure. 467 */ 468 extern int 469 mbc_nodal_get_motion(mbc_nodal_t *mbc); 470 471 /** \brief Put forces to peer. 472 * 473 * \param [in,out] pointer to a valid mbc_nodal_t structure 474 * \param [in] last true when at convergence 475 * 476 * if last is false, before calling this function: 477 * - if MBC_F_REF_NODE(mbc) is true, force and moment must be set in storage pointed to by macros MBC_R_F(mbc), MBC_R_M(mbc) 478 * - if mbc_nodal_t::nodes > 0, nodal forces must be set in storage pointed to by macros MBC_N_F(mbc), MBC_N_M(mbc) 479 * (the latter only if MBC_F_ROT(mbc) != ::MBC_ROT_NONE). 480 * 481 * if last is true and mbc_t::data_and_next is false, the output buffer is not sent; 482 * thus, there is no need to set forces and moments; 483 * otherwise, if mbc_t::data_and_next is true, the output buffer must be filled as described above. 484 * 485 * @return 0 on success, !0 on failure. 486 */ 487 extern int 488 mbc_nodal_put_forces(mbc_nodal_t *mbc, int last); 489 490 491 492 /** 493 * \brief nodal stuff (partially opaque). 494 * 495 * Users do not need to access members directly; 496 * macros documented in the following should be used instead. 497 * 498 * Fields: 499 * 500 * - MBC_Q(mbc): returns a (double *) pointer to the array of generalized coordinates 501 * - MBC_QP(mbc): returns a (double *) pointer to the array of generalized coordinates derivatives 502 * - MBC_P(mbc): returns a (double *) pointer to the array of generalized forces 503 * - MBC_M_KINEMATICS_SIZE(mbc): returns the size of the input buffer 504 * - MBC_M_DYNAMICS_SIZE(mbc): returns the size of the output buffer 505 * - MBC_M_SIZE(mbc): returns the cumulative size of the buffers 506 * - MBC_M_KINEMATICS(mbc): returns a (void *) pointer to the input buffer 507 * - MBC_M_DYNAMICS(mbc): returns a (void *) pointer to the output buffer 508 */ 509 typedef struct { 510 mbc_t mbc; 511 mbc_rigid_t mbcr; 512 513 /* modal data */ 514 uint32_t modes; 515 double *m; 516 #define MBC_Q(mbc) (&(mbc)->m[0]) 517 #define MBC_QP(mbc) (&(mbc)->m[(mbc)->modes]) 518 #define MBC_P(mbc) (&(mbc)->m[2*(mbc)->modes]) 519 #define MBC_M_KINEMATICS(mbc) MBC_Q((mbc)) 520 #define MBC_M_DYNAMICS(mbc) MBC_P((mbc)) 521 #define MBC_M_KINEMATICS_SIZE(mbc) (2*(mbc)->modes*sizeof(double)) 522 #define MBC_M_DYNAMICS_SIZE(mbc) ((mbc)->modes*sizeof(double)) 523 #define MBC_M_SIZE(mbc) (3*(mbc)->modes*sizeof(double)) 524 } mbc_modal_t; 525 526 /** \brief Initialize modal data. 527 * 528 * \param [in,out] mbc pointer to a valid mbc_modal_t structure 529 * \param [in] refnode non-zero if reference node is defined 530 * \param [in] modes number of modes 531 * 532 * Either reference node motion must be defined (refnode != 0), 533 * or modes must be > 0, or both. 534 * 535 * if modes > 0, this function calls malloc(3) to alloc memory 536 * that needs to be freed by calling mbc_modal_destroy() 537 * 538 * @return 0 on success, !0 on failure. 539 */ 540 extern int 541 mbc_modal_init(mbc_modal_t *mbc, int refnode, unsigned modes); 542 543 /** \brief Destroy modal data. 544 * 545 * \param [in,out] mbc pointer to a valid mbc_modal_t structure 546 * 547 * NOTE: does NOT free mbc. 548 * 549 * @return 0 on success, !0 on failure. 550 */ 551 extern int 552 mbc_modal_destroy(mbc_modal_t *mbc); 553 554 /** \brief Negotiate modal data. 555 * 556 * \param [in] mbc pointer to a valid mbc_modal_t structure 557 * 558 * At least reference node motion must be defined 559 * (MBC_F_REF_NODE(mbc) must be true), 560 * or modes > 0 561 * 562 * The socket must be initialized and connected. 563 * 564 * This function sends a negotiation request to the master. 565 * 566 * @return 0 on success, !0 on failure. 567 */ 568 /* 569 * the protocol consists in: 570 * 571 * - negotiation request: 572 * - the negotiation request tag (ES_NEGOTIATION, uint8_t) 573 * - a bunch of flags (uint32_t), containing: 574 * - the type of interface (MBC_MODAL or MBC_NODAL) 575 * - whether a reference node is defined, MBC_REF_NODE OR-ed to previous 576 * - more... 577 * - the number of modes (uint32_t) 578 * 579 * - negotiation response: 580 * - the negotiation response tag (ES_OK or ES_ABORT, uint8_t) 581 */ 582 extern int 583 mbc_modal_negotiate_request(mbc_modal_t *mbc); 584 585 /** \brief Unused. 586 * 587 * companion of above, provided for completeness; not used 588 */ 589 extern int 590 mbc_modal_negotiate_response(mbc_modal_t *mbc); 591 592 /** \brief Get modal motion from peer. 593 * 594 * \param [in,out] pointer to a valid mbc_modal_t structure 595 * 596 * After the call to this function succeeds: 597 * - if MBC_F_REF_NODE(mbc) is true, reference node motion can be accessed using macros MBC_R_X(mbc) and similar; 598 * - if mbc_modal_t::modes > 0, modal motion can be accessed using macros MBC_Q(mbc) and similar. 599 * 600 * @return 0 on success, !0 on failure. 601 */ 602 extern int 603 mbc_modal_get_motion(mbc_modal_t *mbc); 604 605 /** \brief Put forces to peer. 606 * 607 * \param [in,out] mbc pointer to a valid mbc_modal_t structure 608 * \param [in] last true when at convergence 609 * 610 * if last is false, before calling this function: 611 * - if MBC_F_REF_NODE(mbc) is true, force and moment must be set in storage pointed to by macros MBC_R_F(mbc), MBC_R_M(mbc) 612 * - if mbc_modal_t::modes > 0, nodal forces must be set in storage pointed to by macro MBC_P(mbc) 613 * 614 * if last is true and mbc_t::data_and_next is false, the output buffer is not sent; 615 * thus, there is no need to set generalized forces; 616 * otherwise, if mbc_t::data_and_next is true, the output buffer must be filled as described above. 617 * 618 * @return 0 on success, !0 on failure. 619 */ 620 extern int 621 mbc_modal_put_forces(mbc_modal_t *mbc, int last); 622 623 #ifdef __cplusplus 624 } 625 #endif /* __cplusplus */ 626 627 #endif /* MBC_H */ 628