Skip to content

Commit 40f6eab

Browse files
committed
Setup some API functions, move soil info out of anchor design dict
-- addPlatform -- addMooring -- addAnchor -- addSubstation -- addTurbine -- added some mooring API functions too -- addSection -- addConnector -- connectSubcomponents -- initialization/loading now uses API functions -- soil info now stored in anchor.soilProps instead of in design dictionary
1 parent a6cb6e5 commit 40f6eab

File tree

5 files changed

+438
-178
lines changed

5 files changed

+438
-178
lines changed

famodel/anchors/anchor.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ def __init__(self, dd=None, ms=None, r=[0,0,0], aNum=None, id=None,
3030
L2 torpedo anchor shaft length
3131
zlug padeye z elevation (+ down into the soil)
3232
beta angle of plate anchor after keying (optional)
33-
soil_type: <<< not design information
34-
angle: # seabed angle <<< not design information
3533
cost:
3634
matCost: # material cost
3735
instCost: # installation cost
@@ -136,15 +134,15 @@ def makeMoorPyAnchor(self, ms):
136134
return(ms)
137135

138136

139-
def getAnchorCapacity(self,ground_conds=None,installAdj=1,profile=None,loads=None,plot=True):
137+
def getAnchorCapacity(self,ground_cons=None,installAdj=1,profile=None,loads=None,plot=True):
140138
'''
141139
Calls anchor capacity functions developed by Felipe Moreno for the correct anchor type
142140
143141
Parameters
144142
----------
145143
ground_conds : dict, optional
146-
Ground conditions ex: UCS,Em,phi,gamma,effective stress,etc. The default is None.
147-
If no dict provided, the ground conds will be pulled from the dd['soil_properties']
144+
Ground conditions dictionary with the key as the soil type name, values as soil info such as UCS,Em,phi,gamma,effective stress,etc. The default is None.
145+
If no dict provided, the ground conds will be pulled from the anchor soilProps property
148146
installAdj : float, optional
149147
Adjustment to the capacity based on installation (dummy variable for now, but future installation functions
150148
will dictate this value)
@@ -167,8 +165,12 @@ def getAnchorCapacity(self,ground_conds=None,installAdj=1,profile=None,loads=Non
167165
anchType = self.dd['type']
168166
geom = self.dd['design']# geometric anchor information
169167

170-
if not ground_conds:
171-
ground_conds = self.dd['soil_properties']
168+
if not ground_cons:
169+
soil = next(iter(self.soilProps.keys()), None) # soil type
170+
ground_conds = self.soilProps[soil]
171+
else:
172+
soil = next(iter(ground_cons.keys()))
173+
ground_conds = ground_cons[soil]
172174

173175
for key,prop in ground_conds.items():
174176
if isinstance(prop,list) or isinstance(prop,np.ndarray):
@@ -177,7 +179,7 @@ def getAnchorCapacity(self,ground_conds=None,installAdj=1,profile=None,loads=Non
177179
break
178180
else:
179181
ground_conds[key] = prop[0]
180-
soil = self.dd['soil_type'] # soil type
182+
181183

182184
if loads:
183185
# find out if mudline loads or anchor loads
@@ -548,8 +550,8 @@ def makeEqual_TaTm(mudloads):
548550
else:
549551
md = att['obj'].dd['sections'][0]['type']['d_nom']
550552
mw = att['obj'].dd['sections'][0]['type']['w']
551-
soil = self.dd['soil_type']
552-
ground_conds = self.dd['soil_properties']
553+
soil = next(iter(self.soilProps.keys()), None)
554+
ground_conds = self.soilProps[soil]
553555
# update soil conds as needed to be homogeneous
554556
for key,prop in ground_conds.items():
555557
if isinstance(prop,list) or isinstance(prop,np.ndarray):

famodel/helpers.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,7 @@ def getConnectors(c_config, mName, proj):
942942
# create connector object with c_config entries
943943
proj.mooringList[mName].dd['connectors'].append(Connector(**c_config[i]))
944944

945-
def getAnchors(lineAnch, arrayAnchor, proj, mc=None,aNum=0):
945+
def getAnchors(lineAnch, arrayAnchor, proj):
946946
'''Create anchor design dictionary based on a given anchor type
947947
948948
Parameters
@@ -953,10 +953,6 @@ def getAnchors(lineAnch, arrayAnchor, proj, mc=None,aNum=0):
953953
list of anchors listed in array_mooring anchor_data table of ontology yaml.
954954
proj : project class instance
955955
project object to develop anchors for
956-
mc : mooring class instance, optional
957-
mooring class that the anchor is a part of (used only if not a shared anchor). The default is None.
958-
aNum : int, optional
959-
anchor ID in the anchor data table (used only if it is a shared anchor). The default is 0.
960956
961957
Returns
962958
-------
@@ -966,11 +962,6 @@ def getAnchors(lineAnch, arrayAnchor, proj, mc=None,aNum=0):
966962
'''
967963
ad = {'design':{}, 'cost':{}}
968964
ad['design'] = deepcopy(proj.anchorTypes[lineAnch])
969-
if proj.soil_x is not None: # get soil conditions at anchor location if soil info available
970-
if mc:
971-
ad['soil_type'], ad['soil_properties'] = proj.getSoilAtLocation(mc.rA[0], mc.rA[1])
972-
else:
973-
ad['soil_type'], ad['soil_properties'] = proj.getSoilAtLocation(arrayAnchor[aNum-1]['x'],arrayAnchor[aNum-1]['y'])
974965
ad['type'] = proj.anchorTypes[lineAnch]['type']
975966
ad['name'] = lineAnch
976967

famodel/mooring/mooring.py

Lines changed: 106 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -89,32 +89,22 @@ def __init__(self, dd=None, subsystem=None, anchor=None,
8989
# and dict of scaling props (would be used by linedesign) ?
9090
self.n_sec = len(self.dd['sections'])
9191

92+
self.i_con = []
93+
self.i_sec = []
9294
# Turn what's in dd and turn it into Sections and Connectors
9395
for i, con in enumerate(self.dd['connectors']):
9496
if con and 'type' in con:
9597
Cid = con['type']+str(i)
9698
else:
97-
Cid = 'Conn'+str(i)
98-
self.dd['connectors'][i] = Connector(Cid,**self.dd['connectors'][i])
99+
Cid = None
100+
self.addConnector(con, i, id=Cid, insert=False)
99101

100102
for i, sec in enumerate(self.dd['sections']):
101-
self.dd['sections'][i] = Section('Section'+str(i),**self.dd['sections'][i])
102-
#self.dd['connectors'][i ].attach(self.dd['sections'][i], end=0)
103-
#self.dd['connectors'][i+1].attach(self.dd['sections'][i], end=1)
103+
self.addSection(sec['L'],sec['type'],i, insert=False)
104104

105-
# >>> add some error checks for the correct lengths <<<
106-
107-
# Connect them and store them in self(Edge).subcomponents!
108-
subcons = [] # temporary list of node-edge-node... to pass to the function
109-
for i in range(self.n_sec):
110-
subcons.append(self.dd['connectors'][i])
111-
subcons.append(self.dd['sections'][i])
112-
subcons.append(self.dd['connectors'][-1])
113-
self.addSubcomponents(subcons) # Edge method to connect and store em
114-
115-
# Indices of connectors and sections in self.subcomponents list
116-
self.i_con = list(range(0, 2*self.n_sec+1, 2))
117-
self.i_sec = list(range(1, 2*self.n_sec+1, 2))
105+
# connect subcomponents and update i_sec and i_conn lists
106+
self.connectSubcomponents()
107+
118108

119109

120110
# relative positions (variables could be renamed)
@@ -274,7 +264,7 @@ def reposition(self, r_center=None, heading=None, project=None,
274264

275265
for i,att in enumerate(self.attached_to):
276266
iend = self.rA if i == 0 else self.rB
277-
if hasattr(att,'aNum'):
267+
if type(att).__name__ in 'Anchor':
278268
# this is an anchor, move anchor location
279269
att.r = iend
280270
if att.mpAnchor:
@@ -926,3 +916,100 @@ def getEnvelope(self,ang_spacing=45,SFs=True):
926916

927917
return(x,y)
928918

919+
920+
def addSection(self, section_length, section_type, index, id=None, insert=True):
921+
'''
922+
Add a section to the design
923+
924+
Parameters
925+
----------
926+
section_length : float
927+
Length of new section in [m]
928+
section_type : dict
929+
Dictionary of section properties
930+
index : int
931+
New index of section in the mooring design dictionary sections list
932+
id : str/int, optional
933+
Id of section
934+
'''
935+
if not id:
936+
if insert:
937+
for i,sec in enumerate(self.dd['sections']):
938+
# update ids of sections
939+
if i>=index and isinstance(sec, Section):
940+
sec.id = 'Section'+str(i+1)
941+
id='Section'+str(index)
942+
newsection_dd = {'type':section_type,'L':section_length}
943+
newsection = Section(id,**newsection_dd)
944+
if insert:
945+
self.dd['sections'].insert(index, newsection)
946+
else:
947+
self.dd['sections'][index] = newsection
948+
949+
950+
return(newsection)
951+
952+
def addConnector(self, conn_dd, index, id=None, insert=True):
953+
'''
954+
Add a connector to the design
955+
956+
Parameters
957+
----------
958+
conn_dd : dict
959+
Connector design dictionary
960+
index : int
961+
New index of connector in the mooring design dictionary connectors list
962+
id : str or int, optional
963+
ID of new connector
964+
insert : bool, optional
965+
Controls whether to insert a connector in the list or replace an entry with a connector
966+
967+
Returns
968+
-------
969+
Connector object
970+
New connector object added to design dictionary
971+
972+
'''
973+
if not id:
974+
if insert:
975+
for i,conn in enumerate(self.dd['connectors']):
976+
# update ids of connectors
977+
if i>=index and isinstance(conn, Connector):
978+
conn.id = 'Conn'+str(i+1)
979+
id = 'Conn'+str(index)
980+
newconn = Connector(id, **conn_dd)
981+
if insert:
982+
self.dd['connectors'].insert(index, newconn)
983+
else:
984+
self.dd['connectors'][index] = newconn
985+
986+
return(newconn)
987+
988+
def connectSubcomponents(self):
989+
990+
# first disconnect any current subcomponents
991+
for ii in self.i_sec:
992+
self.subcomponents[ii].detachFrom('A')
993+
self.subcomponents[ii].detachFrom('B')
994+
995+
# detach end connectors from platforms/anchors just in case
996+
if len(self.subcomponents)>0:
997+
endattsA = [att['obj'] for att in self.subcomponents[0].attachments.values()]
998+
endattsB = [att['obj'] for att in self.subcomponents[-1].attachments.values()]
999+
for att in endattsA:
1000+
self.subcomponents[0].detach(att)
1001+
for att in endattsB:
1002+
self.subcomponents[-1].detach(att)
1003+
1004+
# Now connect the new set of subcomponents and store them in self(Edge).subcomponents!
1005+
subcons = [] # temporary list of node-edge-node... to pass to the function
1006+
for i in range(self.n_sec):
1007+
subcons.append(self.dd['connectors'][i])
1008+
subcons.append(self.dd['sections'][i])
1009+
subcons.append(self.dd['connectors'][-1])
1010+
self.addSubcomponents(subcons) # Edge method to connect and store em
1011+
1012+
# Indices of connectors and sections in self.subcomponents list
1013+
self.i_con = list(range(0, 2*self.n_sec+1, 2))
1014+
self.i_sec = list(range(1, 2*self.n_sec+1, 2))
1015+

0 commit comments

Comments
 (0)