Skip to content

Commit faf3fc8

Browse files
committed
Mooring adjuster settings now stored in a dict (interim commit)
Mooring: - Moved all adjuster settings into a dictionary, adjuster_settings, rather than a hardcoded set of top-level Mooring attributes since the parameters that are used could change or be customized. - Removed a deepcopy (unlinking) of line type info between dd and ss. A few small comment/format improvements.
1 parent bed28e2 commit faf3fc8

File tree

5 files changed

+61
-39
lines changed

5 files changed

+61
-39
lines changed

famodel/cables/cable.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,3 @@ def updateSpan(self,newSpan):
428428
for i,bs in enumerate(sub.dd['buoyancy_sections']):
429429
bs['L_mid'] = bs['L_mid'] + addL*(i+addS)
430430

431-
432-
433-

famodel/design/LineDesign.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
# New version of LineDesign that uses Subsystem
22

3-
import moorpy as mp # type: ignore
4-
#import moordesign.MoorSolve as msolve
3+
from famodel.mooring.mooring import Mooring
54
from famodel.design.fadsolvers import dsolve2, dopt2, doptPlot
6-
from moorpy.MoorProps import getAnchorProps # type: ignore
7-
from moorpy.helpers import (loadLineProps, getLineProps, # type: ignore
8-
rotationMatrix, getFromDict)
5+
from famodel.helpers import getFromDict
96

10-
from famodel.mooring.mooring import Mooring
7+
import moorpy as mp
8+
from moorpy.MoorProps import getAnchorProps
9+
from moorpy.helpers import (loadLineProps, getLineProps, rotationMatrix)
1110

1211
import numpy as np
1312
import matplotlib.pyplot as plt
@@ -114,7 +113,10 @@ def __init__(self, depth, lineProps=None, **kwargs):
114113
raise Exception("Xindices must be provided.")
115114

116115
# find the largest integer to determine the number of desired design variables
117-
self.nX = 1 + max([ix for ix in self.Xindices if isinstance(ix, int)])
116+
if any([isinstance(ix, int) for ix in self.Xindices]):
117+
self.nX = 1 + max([ix for ix in self.Xindices if isinstance(ix, int)])
118+
else:
119+
self.nX = 0 # no design variables listed
118120

119121
# check for errors in Xindices
120122
for i in range(self.nX):
@@ -314,14 +316,14 @@ def __init__(self, depth, lineProps=None, **kwargs):
314316

315317

316318
# ----- optimization stuff -----
319+
317320
# get design variable bounds and last step size
318321
self.Xmin = getFromDict(kwargs, 'Xmin' , shape=self.nX) # minimum bounds on each design variable
319322
self.Xmax = getFromDict(kwargs, 'Xmax' , shape=self.nX) # maximum bounds on each design variable
320323
self.dX_last = getFromDict(kwargs, 'dX_last', shape=self.nX, default=[]) # 'last' step size for each design variable
321324
if len(self.Xmin) != self.nX or len(self.Xmax) != self.nX or len(self.dX_last) != self.nX:
322325
raise Exception("The size of Xmin/Xmax/dX_last does not match the number of design variables")
323326

324-
325327
# initialize the vector of the last design variables, which each iteration will compare against
326328
self.Xlast = np.zeros(self.nX)
327329

@@ -379,6 +381,7 @@ def __init__(self, depth, lineProps=None, **kwargs):
379381
con['unit'] = conUnitsDict[con['name']]
380382
else:
381383
raise Exception(f"The constraint name '{con['name']}' is not recognized.")
384+
382385
# set up list of active constraint functions
383386
self.conList = []
384387
self.convals = np.zeros(len(self.constraints)) # array to hold constraint values

famodel/design/layout.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -881,9 +881,12 @@ def updateLayout(self, X, level=0, refresh=False):
881881
#print(self.nt, len(self.turb_depth), X)
882882
#print(self.turb_coords)
883883

884-
# Update Paltform class
884+
# Update each turbine's platform and mooring system
885885
for i in range(self.nt):
886-
self.platformList[i].setPosition(self.turb_coords[i], heading=self.turb_rot[i], degrees=False, project = self)
886+
887+
self.platformList[i].setPosition(self.turb_coords[i],
888+
heading=self.turb_rot[i], degrees=False, project=self)
889+
887890
# switch anchor type
888891
anchs = self.platformList[i].getAnchors()
889892
for anch in anchs.values():

famodel/mooring/mooring.py

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,9 @@ def reposition(self, r_center=None, heading=None, project=None,
395395
self.i_line = 0
396396

397397

398-
if hasattr(self,'slope'):
399-
self.adjuster(self, method = 'pretension', r=r_centerB, project=project, target = self.target, i_line = self.i_line, slope = self.slope)
398+
if 'slope'in self.adjuster_settings:
399+
self.adjuster_settings.update(dict(method='pretension', r=r_centerB))
400+
self.adjuster(self, project)
400401

401402
else:
402403

@@ -408,8 +409,9 @@ def reposition(self, r_center=None, heading=None, project=None,
408409
else:
409410
print('Warning: depth of mooring line, anchor, and subsystem must be updated manually.')
410411

411-
self.setEndPosition(np.hstack([self.rB[:2] + self.span*u, self.z_anch]), 'a', sink=True)
412-
self.adjuster(self, method = 'horizontal', r=r_centerB, project=project, target = self.target, i_line = self.i_line)
412+
self.setEndPosition(np.hstack([self.rB[:2] + self.span*u, self.z_anch]), 'a', sink=True)
413+
self.adjuster_settings.update(dict(method='horizontal', r=r_centerB))
414+
self.adjuster(self, project)
413415

414416
elif self.shared == 1: # set position of end A at platform end A if no fairlead objects
415417
if not len(self.subcons_A[0].attachments) > 1:
@@ -484,7 +486,9 @@ def configureAdjuster(self, adjuster=None, method='horizontal',
484486
i_line=0, span=None, project=None, target=None):
485487
'''Configures adjuster function for mooring object
486488
487-
#MH: >>> moved in from helpers. To be worked on <<<
489+
#MH: >>> moved in from helpers. To be worked on. Support passing any dict of settings... <<<
490+
491+
The following are now stored in Mooring.adjuster_settings: target, i_line, slope
488492
489493
mooring : FAModel Mooring object
490494
adjuster : function, optional
@@ -501,6 +505,9 @@ def configureAdjuster(self, adjuster=None, method='horizontal',
501505
target : target value(s) for method - either pretension value or horizontal force value in x and y
502506
503507
'''
508+
509+
asets = self.adjuster_settings # shorthand for the settings dictionary
510+
504511
#calculate target pretension or horizontal tension if none provided
505512
if adjuster != None and target == None:
506513
targetdd = deepcopy(self.dd)
@@ -512,21 +519,21 @@ def configureAdjuster(self, adjuster=None, method='horizontal',
512519
self.createSubsystem(dd=targetdd)
513520

514521
if method == 'horizontal':
515-
self.target = np.linalg.norm(self.ss.fB_L[:2])
522+
asets['target'] = np.linalg.norm(self.ss.fB_L[:2])
516523
elif method =='pretension':
517-
self.target = np.linalg.norm(self.ss.fB_L)
524+
asets['target'] = np.linalg.norm(self.ss.fB_L)
518525
else:
519526
raise Exception('Invalid adjustment method. Must be pretension or horizontal')
520527
# return mooring depth to accurate val
521528
if not self.shared:
522529
depth = project.getDepthAtLocation(self.rA[0], self.rA[1])
523530
self.rA[2] = -depth
524531
else:
525-
self.target = target
532+
asets['target'] = target
526533

527534
if adjuster!= None:
528535
self.adjuster = adjuster
529-
self.i_line = i_line
536+
asets['i_line'] = i_line
530537

531538
# check if method is 'pretension' then save slope
532539
if method == 'pretension':
@@ -537,11 +544,11 @@ def configureAdjuster(self, adjuster=None, method='horizontal',
537544

538545
#calculate mooring slope using base depth
539546
#**** this assumes that the mooring system is designed for the base depth*****
540-
self.slope = (project.depth+self.rB[2]) / self.dd['span']
547+
asets['slope'] = (project.depth+self.rB[2]) / self.dd['span']
541548

542549
else:
543550
if span:
544-
self.slope = (project.depth+self.rB[2]) / span
551+
asets['slope'] = (project.depth+self.rB[2]) / span
545552
else:
546553
raise Exception('Span required to perform adjustment')
547554

@@ -714,8 +721,8 @@ def createSubsystem(self, case=0, dd=None, ms=None, ss_number=None):
714721
# run through each line section and collect the length and type
715722
for sec in secs:
716723
lengths.append(sec['L'])
717-
types.append(deepcopy(sec['type'])) # list of type names
718-
724+
types.append(sec['type']) #types.append(deepcopy(sec['type'])) # list of type names
725+
# <<< is there a reason we were deepcopying (unlinking) this? <<<
719726

720727
# make the lines and set the points
721728
ss.makeGeneric(lengths, types,
@@ -1817,20 +1824,24 @@ def fairleads(self, end):
18171824
# ind[level] += 1
18181825

18191826

1820-
def adjustMooring(mooring, method = 'horizontal', r=[0,0,0], project=None, target=1e6,
1821-
i_line = [0], slope = 0.58, display=False ):
1822-
'''Custom function to adjust a mooring, called by
1823-
Mooring.adjust. Fairlead point should have already
1824-
been adjusted.
1827+
def adjustMooring(mooring, project, display=0):
1828+
'''Default/example function to adjust a mooring after it has been
1829+
repositioned. This function would be assigned to Mooring.adjuster,
1830+
and it is expected that settings for the adjustment process are
1831+
stored in a Mooring.adjuster_settings dictionary.
1832+
Note that the mooring line endpoints should already be in place when
1833+
this function is called.
1834+
1835+
This example function looks for some of the following types of info:
18251836
1826-
There are two methods: "pretension" geometrically adjusts the anchor point and matches pretension, intended for taut moorings.
1827-
"horizontal" leaves anchor point in the same position and matches the horizontal forces, intended for catenary and semi-taut moorings
1837+
method = 'horizontal', r=[0,0,0], project=None, target=1e6,
1838+
i_line = [0], slope = 0.58, display=False
1839+
1840+
There are two methods: "pretension" geometrically adjusts the anchor
1841+
point and matches pretension, intended for taut moorings.
1842+
"horizontal" leaves anchor point in the same position and matches the
1843+
horizontal forces, intended for catenary and semi-taut moorings
18281844
1829-
Parameters
1830-
----------
1831-
mooring : FAModel Mooring object
1832-
r : array
1833-
platform center location (only used for pretension method)
18341845
project : FAModel Project object this is a part of.
18351846
This is a required input for the "pretension" option to correctly move the anchor position, not used in the 'horizontal method'
18361847
target_pretension : float
@@ -1839,10 +1850,17 @@ def adjustMooring(mooring, method = 'horizontal', r=[0,0,0], project=None, targe
18391850
List of indexes of line section to adjust
18401851
slope: float
18411852
depth over span for baseline case (to match same geometric angle for 'pretension' option)
1853+
'''
18421854

1843-
'''
18441855
from moorpy.helpers import dsolve2
1856+
18451857
ss = mooring.ss # shorthand for the mooring's subsystem
1858+
asets = mooring.adjuster_settings # shorthand for settings dict
1859+
method = getFromDict(asets, 'method', default='horizontal')
1860+
r = getFromDict(asets, 'r', default=[0,0,0])
1861+
target = getFromDict(asets, 'target', default=1e6) #<<< shouldn't have a default
1862+
i_line = getFromDict(asets, 'i_line', default=[0])
1863+
slope = getFromDict(asets, 'slope', default=.58) #<<< shouldn't have a default
18461864

18471865
if method == 'pretension':
18481866

famodel/platform/platform.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ def setPosition(self, r, heading=None, degrees=False,project=None, update_moorin
119119
moor.dd['span'] = np.linalg.norm(moor.rA[:2]-moor.rB[:2])
120120
moor.span=moor.dd['span']
121121

122+
122123
def mooringSystem(self,rotateBool=0,mList=None,bodyInfo=None, project=None):
123124
'''
124125
Create a MoorPy system for the platform based on the mooring subsystems provided in

0 commit comments

Comments
 (0)