Skip to content

Commit 5379ca0

Browse files
authored
Merge pull request #2663 from luwang00/f/HD_C_AM
HydroDyn C-binding: Added mass matrix
2 parents fca21fd + f9a4e88 commit 5379ca0

File tree

2 files changed

+323
-11
lines changed

2 files changed

+323
-11
lines changed

modules/hydrodyn/python-lib/hydrodyn_library.py

Lines changed: 113 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,19 @@ def _initialize_routines(self):
199199
]
200200
self.HydroDyn_C_CalcOutput.restype = c_int
201201

202+
self.HydroDyn_C_CalcOutput_and_AddedMass.argtypes = [
203+
POINTER(c_double), # Time_C
204+
POINTER(c_int), # numNodePts -- number of points expecting motions/loads
205+
POINTER(c_float), # nodePos -- node positions in flat array of 6*numNodePts
206+
POINTER(c_float), # nodeVel -- node velocities in flat array of 6*numNodePts
207+
POINTER(c_float), # nodeFrc -- node forces/moments in flat array of 6*numNodePts
208+
POINTER(c_float), # nodeAdm -- node added mass matrix in flat array of 6*numNodePts*6*numNodePts
209+
POINTER(c_float), # Output Channel Values
210+
POINTER(c_int), # ErrStat_C
211+
POINTER(c_char) # ErrMsg_C
212+
]
213+
self.HydroDyn_C_CalcOutput_and_AddedMass.restype = c_int
214+
202215
self.HydroDyn_C_UpdateStates.argtypes = [
203216
POINTER(c_double), # Time_C
204217
POINTER(c_double), # TimeNext_C
@@ -259,7 +272,7 @@ def hydrodyn_init(self, seast_input_string_array, hd_input_string_array):
259272
raise Exception("\nHydroDyn terminated prematurely.")
260273

261274
# Make a flat 1D array of position info:
262-
# [x2,y1,z1,Rx1,Ry1,Rz1, x2,y2,z2,Rx2,Ry2,Rz2 ...]
275+
# [x1,y1,z1,Rx1,Ry1,Rz1, x2,y2,z2,Rx2,Ry2,Rz2 ...]
263276
nodeInitLoc_flat = [pp for p in self.initNodePos for pp in p]
264277
nodeInitLoc_flat_c = (c_float * (6 * self.numNodePts))(0.0,)
265278
for i, p in enumerate(nodeInitLoc_flat):
@@ -302,16 +315,16 @@ def hydrodyn_init(self, seast_input_string_array, hd_input_string_array):
302315
def hydrodyn_calcOutput(self, time, nodePos, nodeVel, nodeAcc, nodeFrcMom, outputChannelValues):
303316

304317
# Check input motion info
305-
self.check_input_motions(nodePos,nodeVel,nodeAcc)
318+
self.check_input_motions(time,nodePos,nodeVel,nodeAcc)
306319

307320
# set flat arrays for inputs of motion
308-
# Position -- [x2,y1,z1,Rx1,Ry1,Rz1, x2,y2,z2,Rx2,Ry2,Rz2 ...]
321+
# Position -- [x1,y1,z1,Rx1,Ry1,Rz1, x2,y2,z2,Rx2,Ry2,Rz2 ...]
309322
nodePos_flat = [pp for p in nodePos for pp in p]
310323
nodePos_flat_c = (c_float * (6 * self.numNodePts))(0.0,)
311324
for i, p in enumerate(nodePos_flat):
312325
nodePos_flat_c[i] = c_float(p)
313326

314-
# Velocity -- [Vx2,Vy1,Vz1,RVx1,RVy1,RVz1, Vx2,Vy2,Vz2,RVx2,RVy2,RVz2 ...]
327+
# Velocity -- [Vx1,Vy1,Vz1,RVx1,RVy1,RVz1, Vx2,Vy2,Vz2,RVx2,RVy2,RVz2 ...]
315328
nodeVel_flat = [pp for p in nodeVel for pp in p]
316329
nodeVel_flat_c = (c_float * (6 * self.numNodePts))(0.0,)
317330
for i, p in enumerate(nodeVel_flat):
@@ -331,7 +344,7 @@ def hydrodyn_calcOutput(self, time, nodePos, nodeVel, nodeAcc, nodeFrcMom, outpu
331344

332345
# Run HydroDyn_C_CalcOutput
333346
self.HydroDyn_C_CalcOutput(
334-
byref(c_double(time)), # IN: time at which to calculate output forces
347+
byref(c_double(time)), # IN: time at which to calculate output forces
335348
byref(c_int(self.numNodePts)), # IN: number of attachment points expected (where motions are transferred into HD)
336349
nodePos_flat_c, # IN: positions - specified by user
337350
nodeVel_flat_c, # IN: velocities at desired positions
@@ -359,11 +372,76 @@ def hydrodyn_calcOutput(self, time, nodePos, nodeVel, nodeAcc, nodeFrcMom, outpu
359372
for k in range(0,self.numChannels):
360373
outputChannelValues[k] = float(outputChannelValues_c[k])
361374

375+
# hydrodyn_calcOutput_and_addedMass ------------------------------------------------------------------------------------------------------
376+
def hydrodyn_calcOutput_and_addedMass(self, time, nodePos, nodeVel, nodeFrcMom, nodeAdm, outputChannelValues):
377+
378+
# Check input motion info
379+
self.check_input_motions_noAcc(time,nodePos,nodeVel)
380+
381+
# set flat arrays for inputs of motion
382+
# Position -- [x1,y1,z1,Rx1,Ry1,Rz1, x2,y2,z2,Rx2,Ry2,Rz2 ...]
383+
nodePos_flat = [pp for p in nodePos for pp in p]
384+
nodePos_flat_c = (c_float * (6 * self.numNodePts))(0.0,)
385+
for i, p in enumerate(nodePos_flat):
386+
nodePos_flat_c[i] = c_float(p)
387+
388+
# Velocity -- [Vx1,Vy1,Vz1,RVx1,RVy1,RVz1, Vx2,Vy2,Vz2,RVx2,RVy2,RVz2 ...]
389+
nodeVel_flat = [pp for p in nodeVel for pp in p]
390+
nodeVel_flat_c = (c_float * (6 * self.numNodePts))(0.0,)
391+
for i, p in enumerate(nodeVel_flat):
392+
nodeVel_flat_c[i] = c_float(p)
393+
394+
# Resulting Forces/moments -- [Fx1,Fy1,Fz1,Mx1,My1,Mz1, Fx2,Fy2,Fz2,Mx2,My2,Mz2 ...]
395+
nodeFrc_flat_c = (c_float * (6 * self.numNodePts))(0.0,)
396+
397+
# Resulting Added-mass matrix
398+
nodeAdm_flat_c = (c_float * (6 * self.numNodePts * 6 * self.numNodePts))(0.0,)
399+
400+
# Set up output channels
401+
outputChannelValues_c = (c_float * self.numChannels)(0.0,)
402+
403+
# Run HydroDyn_C_CalcOutput_and_AddedMass
404+
self.HydroDyn_C_CalcOutput_and_AddedMass(
405+
byref(c_double(time)), # IN: time at which to calculate output forces
406+
byref(c_int(self.numNodePts)), # IN: number of attachment points expected (where motions are transferred into HD)
407+
nodePos_flat_c, # IN: positions - specified by user
408+
nodeVel_flat_c, # IN: velocities at desired positions
409+
nodeFrc_flat_c, # OUT: resulting forces/moments array
410+
nodeAdm_flat_c, # OUT: resulting forces/moments array
411+
outputChannelValues_c, # OUT: output channel values as described in input file
412+
byref(self.error_status_c), # OUT: ErrStat_C
413+
self.error_message_c # OUT: ErrMsg_C
414+
)
415+
416+
self.check_error()
417+
418+
## Reshape Force/Moment into [N,6]
419+
count = 0
420+
for j in range(0,self.numNodePts):
421+
nodeFrcMom[j,0] = nodeFrc_flat_c[count]
422+
nodeFrcMom[j,1] = nodeFrc_flat_c[count+1]
423+
nodeFrcMom[j,2] = nodeFrc_flat_c[count+2]
424+
nodeFrcMom[j,3] = nodeFrc_flat_c[count+3]
425+
nodeFrcMom[j,4] = nodeFrc_flat_c[count+4]
426+
nodeFrcMom[j,5] = nodeFrc_flat_c[count+5]
427+
count = count + 6
428+
429+
## Reshape added-mass matrix into [6N,6N]
430+
count = 0
431+
for j in range(0,6*self.numNodePts):
432+
for k in range(0,6*self.numNodePts):
433+
nodeAdm[k,j] = nodeAdm_flat_c[count]
434+
count = count + 1
435+
436+
# Convert output channel values back into python
437+
for k in range(0,self.numChannels):
438+
outputChannelValues[k] = float(outputChannelValues_c[k])
439+
362440
# hydrodyn_updateStates ------------------------------------------------------------------------------------------------------------
363441
def hydrodyn_updateStates(self, time, timeNext, nodePos, nodeVel, nodeAcc, nodeFrcMom):
364442

365443
# Check input motion info
366-
self.check_input_motions(nodePos,nodeVel,nodeAcc)
444+
self.check_input_motions(time,nodePos,nodeVel,nodeAcc)
367445

368446
# set flat arrays for inputs of motion
369447
# Position -- [x2,y1,z1,Rx1,Ry1,Rz1, x2,y2,z2,Rx2,Ry2,Rz2 ...]
@@ -389,7 +467,7 @@ def hydrodyn_updateStates(self, time, timeNext, nodePos, nodeVel, nodeAcc, nodeF
389467

390468
# Run HydroDyn_UpdateStates_c
391469
self.HydroDyn_C_UpdateStates(
392-
byref(c_double(time)), # IN: time at which to calculate output forces
470+
byref(c_double(time)), # IN: time at which to calculate output forces
393471
byref(c_double(timeNext)), # IN: time T+dt we are stepping to
394472
byref(c_int(self.numNodePts)), # IN: number of attachment points expected (where motions are transferred into HD)
395473
nodePos_flat_c, # IN: positions - specified by user
@@ -425,10 +503,9 @@ def check_error(self):
425503
raise Exception("\nHydroDyn terminated prematurely.")
426504

427505

428-
def check_input_motions(self,nodePos,nodeVel,nodeAcc):
506+
def check_input_motions(self,time,nodePos,nodeVel,nodeAcc):
429507
# make sure number of nodes didn't change for some reason
430508
if self._initNumNodePts != self.numNodePts:
431-
# @ANDY TODO: `time` is not available here so this would be a runtime error
432509
print(f"At time {time}, the number of node points changed from initial value of {self._initNumNodePts}. This is not permitted during the simulation.")
433510
self.hydrodyn_end()
434511
raise Exception("\nError in calling HydroDyn library.")
@@ -466,6 +543,33 @@ def check_input_motions(self,nodePos,nodeVel,nodeAcc):
466543
raise Exception("\nHydroDyn terminated prematurely.")
467544

468545

546+
def check_input_motions_noAcc(self,time,nodePos,nodeVel):
547+
# make sure number of nodes didn't change for some reason
548+
if self._initNumNodePts != self.numNodePts:
549+
print(f"At time {time}, the number of node points changed from initial value of {self._initNumNodePts}. This is not permitted during the simulation.")
550+
self.hydrodyn_end()
551+
raise Exception("\nError in calling HydroDyn library.")
552+
553+
# Verify that the shape of positions array is correct
554+
if nodePos.shape[1] != 6:
555+
print("Expecting a Nx6 array of node positions (nodePos) with second index for [x,y,z,Rx,Ry,Rz]")
556+
self.hydrodyn_end()
557+
raise Exception("\nHydroDyn terminated prematurely.")
558+
if nodePos.shape[0] != self.numNodePts:
559+
print("Expecting a Nx6 array of node positions (nodePos) with first index for node number.")
560+
self.hydrodyn_end()
561+
raise Exception("\nHydroDyn terminated prematurely.")
562+
563+
# Verify that the shape of velocities array is correct
564+
if nodeVel.shape[1] != 6:
565+
print("Expecting a Nx6 array of node velocities (nodeVel) with second index for [x,y,z,Rx,Ry,Rz]")
566+
self.hydrodyn_end()
567+
raise Exception("\nHydroDyn terminated prematurely.")
568+
if nodeVel.shape[0] != self.numNodePts:
569+
print("Expecting a Nx6 array of node velocities (nodeVel) with first index for node number.")
570+
self.hydrodyn_end()
571+
raise Exception("\nHydroDyn terminated prematurely.")
572+
469573

470574
@property
471575
def output_channel_names(self):

0 commit comments

Comments
 (0)