Skip to content

Commit 31a81e7

Browse files
committed
More updates to anchor.getSize to get GitHub Actions passing
DISCLAIMER: I have only been testing this for a specific application - it needs more tests for many other scenarios - Included the capability for mudline forces to be read in rather than just Ha/Va loads - - requires recalculating the padeye loads through getLugForces each iteration (need a better system like updateDesign to only run these functions once) - Included the conFunH and conFunV constraint functions in the analysis again - things work the same for suction piles and D&G piles with or without them (for this specific case so far) - small reorganization to deal with later - added a separate constraint list for non-suction pile/D&G anchors to just ensure the FS dictionary values stay above 1 (solves the GitHub Actions issue for a drag anchor) - still needs some more organization
1 parent d50c1c2 commit 31a81e7

File tree

1 file changed

+62
-29
lines changed

1 file changed

+62
-29
lines changed

famodel/anchors/anchor.py

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,10 @@ def objective(vars, args):
850850
self.dd['design'].update(newGeom)
851851
if 'suction' in self.dd['type'] and not fix_zlug:
852852
self.dd['design']['zlug'] = (2/3)*newGeom['L']
853+
854+
if 'Hm' in input_loads or 'Vm' in input_loads:
855+
anchor_loads = self.getLugForces(mudloads=input_loads)
856+
input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary
853857
# get results
854858
results = self.getAnchorCapacity(loads=input_loads, plot=False)
855859

@@ -860,6 +864,10 @@ def conFun_LD(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs):
860864
newGeom = dict(zip(geomKeys, vars))
861865
self.dd['design'].update(newGeom)
862866

867+
if 'Hm' in input_loads or 'Vm' in input_loads:
868+
anchor_loads = self.getLugForces(mudloads=input_loads)
869+
input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary
870+
863871
results = self.getAnchorCapacity(loads=input_loads, plot=False)
864872

865873
convalA = newGeom['L']/newGeom['D'] - LD_con[0]
@@ -873,6 +881,9 @@ def conFun_LD(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs):
873881
return(conval)
874882
# constraint to ensure unity check > 1 for suction buckets
875883
def conFun_Suction(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs):
884+
if 'Hm' in input_loads or 'Vm' in input_loads:
885+
anchor_loads = self.getLugForces(mudloads=input_loads)
886+
input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary
876887
results = self.getAnchorCapacity(loads=input_loads, plot=False)
877888
#conval = results['UC'] - 1
878889
conval = 1 - results['UC']
@@ -883,6 +894,9 @@ def conFun_DandG(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minf
883894

884895
newGeom = dict(zip(geomKeys, vars))
885896
self.dd['design'].update(newGeom)
897+
if 'Hm' in input_loads or 'Vm' in input_loads:
898+
anchor_loads = self.getLugForces(mudloads=input_loads)
899+
input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary
886900
results = self.getAnchorCapacity(loads=input_loads, plot=False)
887901

888902
return np.array([0.05*newGeom['D'] - results['Lateral displacement'] , 0.25 - results['Rotational displacement']])
@@ -894,7 +908,11 @@ def conFunH(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs):
894908
# # if results['UC'] < 1:
895909
# # conval = -1*(results['UC'])
896910
# else:
897-
FS = self.getFS(loads=input_loads)
911+
if 'Hm' in input_loads or 'Vm' in input_loads:
912+
anchor_loads = self.getLugForces(mudloads=input_loads)
913+
input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary
914+
minfs = dict(Ha=minfs['Hm'], Va=minfs['Vm'])
915+
FS, _, _ = self.getFS(loads=input_loads, acceptance_crit=minfs)
898916
conval = FS['Ha'] - 1
899917
# for key,val in FS.items():
900918

@@ -904,7 +922,11 @@ def conFunH(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs):
904922
return(conval)
905923

906924
def conFunV(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs):
907-
FS = self.getFS(loads=input_loads)
925+
if 'Hm' in input_loads or 'Vm' in input_loads:
926+
anchor_loads = self.getLugForces(mudloads=input_loads)
927+
input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary
928+
minfs = dict(Ha=minfs['Hm'], Va=minfs['Vm'])
929+
FS, _, _ = self.getFS(loads=input_loads, acceptance_crit=minfs)
908930
# special case for DEAs
909931
if minfs['Va'] == 0:
910932
conval = 1
@@ -919,6 +941,9 @@ def conBounds(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs):
919941
newGeom = dict(zip(geomKeys, vars))
920942
self.dd['design'].update(newGeom)
921943

944+
if 'Hm' in input_loads or 'Vm' in input_loads:
945+
anchor_loads = self.getLugForces(mudloads=input_loads)
946+
input_loads = dict(Ha=anchor_loads['Ha'], Va=anchor_loads['Va']) # overwrite the input_loads dictionary
922947
results = self.getAnchorCapacity(loads=input_loads, plot=False)
923948

924949
bound_L_lower = newGeom['L'] - geomBounds[0][0]
@@ -931,17 +956,9 @@ def conBounds(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs):
931956
# - - - - - Setup & Optimization
932957
from scipy.optimize import minimize
933958
from copy import deepcopy
959+
934960
anchType = self.dd['type']
935-
if not loads:
936-
loads = self.loads
937-
938-
if not 'Ha' in loads:
939-
loads = self.getLugForces(mudloads=loads)
940-
941-
# suction bucket needs to be loads*FS because of capacity envelope calculations in capacity function
942-
input_loads = {'Ha':loads['Ha']*minfs['Ha'],'Va':loads['Va']*minfs['Va']}
943961

944-
945962
# loads['Ha'] = minfs['Ha']*loads['Ha']
946963
# loads['Va'] = minfs['Va']*loads['Va']
947964
startGeom = dict(zip(geomKeys,geom))
@@ -963,6 +980,21 @@ def conBounds(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs):
963980
geom.pop(zlug_loc)
964981
if geomBounds:
965982
geomBounds.pop(zlug_loc)
983+
984+
if not loads:
985+
loads = self.loads
986+
987+
if not 'Ha' in loads:
988+
loads = self.getLugForces(mudloads=loads)
989+
990+
# suction bucket needs to be loads*FS because of capacity envelope calculations in capacity function
991+
if ('Hm' in loads and 'Vm' in loads) and ('Hm' in minfs and 'Vm' in minfs):
992+
input_loads = {'Hm':loads['Hm']*minfs['Hm'], 'Vm':loads['Vm']*minfs['Vm']}
993+
else:
994+
input_loads = {'Ha':loads['Ha']*minfs['Ha'],'Va':loads['Va']*minfs['Va']}
995+
996+
997+
966998

967999
# Initial guess for geometry
9681000
initial_guess = geom # [val for val in startGeom.values()] # Input values for geometry
@@ -975,28 +1007,30 @@ def conBounds(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs):
9751007

9761008
constraints = [{'type':'ineq','fun':conFun_LD,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
9771009
{'type':'ineq','fun':conFun_Suction,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
978-
#{'type':'ineq','fun':conFunH,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
979-
#{'type':'ineq','fun':conFunV,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
1010+
{'type':'ineq','fun':conFunH,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
1011+
{'type':'ineq','fun':conFunV,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
9801012
{'type':'ineq','fun':conBounds,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}]
9811013

982-
else:
983-
# bounds = None
1014+
elif 'dandg' in anchType:
9841015
constraints = [{'type':'ineq','fun':conFun_LD,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
9851016
{'type':'ineq','fun':conFun_DandG,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
986-
#{'type':'ineq','fun':conFunH,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
987-
#{'type':'ineq','fun':conFunV,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
1017+
{'type':'ineq','fun':conFunH,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
1018+
{'type':'ineq','fun':conFunV,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
9881019
{'type':'ineq','fun':conBounds,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}]
9891020

1021+
else:
1022+
constraints = [{'type':'ineq','fun':conFunH,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)},
1023+
{'type':'ineq','fun':conFunV,'args':(geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs)}]
1024+
9901025
# Run the optimization to find sizing that satisfy UC close to 1
9911026
print('optimizing anchor size')
9921027

993-
if not geomBounds:
994-
solution = minimize(objective, initial_guess, args=(geomKeys, input_loads, fix_zlug), method="COBYLA",
995-
constraints=constraints, options={'rhobeg':0.1, 'catol':0.001})
1028+
if 'suction' in anchType or 'dandg' in anchType:
1029+
solution = minimize(objective, initial_guess, args=dict(geomKeys=geomKeys, input_loads=input_loads, fix_zlug=fix_zlug, LD_con=LD_con, geomBounds=geomBounds, minfs=minfs),
1030+
method="COBYLA", constraints=constraints, options={'rhobeg':0.1, 'catol':0.001})
9961031
else:
997-
solution = minimize(objective, initial_guess, args=dict(geomKeys=geomKeys, input_loads=input_loads, fix_zlug=fix_zlug, LD_con=LD_con, geomBounds=geomBounds, minfs=minfs), method="COBYLA",
998-
constraints=constraints,
999-
options={'rhobeg':0.1, 'catol':0.001})
1032+
solution = minimize(objective, initial_guess, args=dict(geomKeys=geomKeys, input_loads=input_loads, fix_zlug=fix_zlug, LD_con=LD_con, geomBounds=geomBounds, minfs=minfs),
1033+
method="COBYLA", constraints=constraints, options={'rhobeg':0.1, 'catol':0.001})
10001034

10011035
FS, acceptance, FSdiff = self.getFS(loads=input_loads, acceptance_crit=minfs)
10021036

@@ -1024,13 +1058,12 @@ def conBounds(vars, geomKeys, input_loads, fix_zlug, LD_con, geomBounds, minfs):
10241058

10251059
print('new initial guess',initial_guess)
10261060
# re-run optimization
1027-
if not geomBounds:
1028-
solution = minimize(objective, initial_guess, args=(geomKeys, input_loads, fix_zlug), method="COBYLA",
1029-
constraints=constraints, options={'disp':True, 'rhobeg':0.1, 'catol':0.0001})
1061+
if 'suction' in anchType or 'dandg' in anchType:
1062+
solution = minimize(objective, initial_guess, args=dict(geomKeys=geomKeys, input_loads=input_loads, fix_zlug=fix_zlug, LD_con=LD_con, geomBounds=geomBounds, minfs=minfs),
1063+
method="COBYLA", constraints=constraints, options={'rhobeg':0.1, 'catol':0.001})
10301064
else:
1031-
solution = minimize(objective, initial_guess, args=(geomKeys, input_loads, fix_zlug), method="COBYLA",
1032-
constraints=constraints, bounds=geomBounds,
1033-
options={'rhobeg':0.1, 'catol':0.001,'maxiter':400})
1065+
solution = minimize(objective, initial_guess, args=dict(geomKeys=geomKeys, input_loads=input_loads, fix_zlug=fix_zlug, LD_con=LD_con, geomBounds=geomBounds, minfs=minfs),
1066+
method="COBYLA", constraints=constraints, options={'rhobeg':0.1, 'catol':0.001})
10341067
# re-determine FS and diff from minFS
10351068
FS, acceptance, FSdiff = self.getFS(loads=input_loads, acceptance_crit=minfs)
10361069
count += 1

0 commit comments

Comments
 (0)