Skip to content

Commit 1b93d0d

Browse files
committed
WIP update calc_midpoint, bug fixes, test with shared example
-- added new helper method for calculating midpoint of 2 points - calc_midpoint calculates midpoint of 2 points, useful for calculating where span starts from bridles -- fixed some bugs - updated to determine anchor end point from midpoint of end point(s) - if not a bridle, midpoint is just the actual point - fixed small bugs in famodel_base - fixed small bugs in helpers.getMoorings to add connectors around subsections as needed -- added bridle to shared example and tested - plotting does not currently work, need to fix base class or somewhere to update rA and rB of each section - this does not happen with node.setPosition because that only sets node position and one end of the attached section
1 parent 94d2fe3 commit 1b93d0d

File tree

6 files changed

+101
-37
lines changed

6 files changed

+101
-37
lines changed

examples/Inputs/OntologySample600m_shared.yaml

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,10 @@ platforms:
12091209
r: 58
12101210
z: -14
12111211
headings: [30, 150, 270] # headings in degrees for the fairlead (if multiple headings, the fairlead will be repeated for each heading)
1212+
- name: fairleads2
1213+
r_rel: [-57.779,-5.055, -14]
1214+
- name: fairleads3
1215+
r_rel: [-57.779, 5.055, -14]
12121216
rFair : 40.5 # platform fairlead radius
12131217
zFair : -20 # platform fairlead z-location
12141218
type : FOWT
@@ -1311,9 +1315,9 @@ mooring_systems:
13111315
ms1:
13121316
name: 3-line semi-taut polyester mooring system with one line shared anchor
13131317

1314-
keys: [MooringConfigID, heading, anchorType, fairleads]
1318+
keys: [MooringConfigID, heading, anchorType, fairlead]
13151319
data:
1316-
- [ rope_1, 270 , suction_pile1, 3 ]
1320+
- [ rope_1_bridle, 270 , suction_pile1, [4,5] ]
13171321
- [ rope_1, 135 , suction_pile1, 2 ]
13181322

13191323
ms2:
@@ -1327,14 +1331,14 @@ mooring_systems:
13271331
ms3:
13281332
name: 3-line semi-taut polyester mooring system with one line shared anchor and one shared line
13291333

1330-
keys: [MooringConfigID, heading, anchorType, fairleads]
1334+
keys: [MooringConfigID, heading, anchorType, fairlead]
13311335
data:
13321336
- [ rope_1, 45 , suction_pile1, 1 ]
13331337

13341338
ms4:
13351339
name: 3 line taut poly mooring system
13361340

1337-
keys: [MooringConfigID, heading, anchorType, fairleads]
1341+
keys: [MooringConfigID, heading, anchorType, fairlead]
13381342
data:
13391343
- [ rope_1, 45 , suction_pile1, 1 ]
13401344
- [ rope_1, 135 , suction_pile1, 2 ]
@@ -1358,6 +1362,27 @@ mooring_line_configs:
13581362
length: 1170 # [m] usntretched length of line section
13591363
adjustable: True # flags that this section could be adjusted to accommodate different spacings...
13601364

1365+
rope_1_bridle: # mooring line configuration identifier
1366+
1367+
name: rope configuration 1 with a bridle # descriptive name
1368+
1369+
span: 1131.37
1370+
1371+
1372+
sections: #in order from anchor to fairlead
1373+
- type: chain_155mm
1374+
length: 20
1375+
- type: rope # ID of a mooring line section type
1376+
length: 1120 # [m] usntretched length of line section
1377+
adjustable: True # flags that this section could be adjusted to accommodate different spacings...
1378+
- subsections: # bridle sections for end B
1379+
- - type: rope
1380+
length: 50
1381+
- connectorType: shackle
1382+
- - type: rope
1383+
length: 50
1384+
- connectorType: shackle
1385+
13611386
rope_shared:
13621387
name: shared rope
13631388

examples/example_sharedmoorings.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
os.chdir(input_directory)
1919

2020
# load in yaml
21-
project = Project(file=filename,raft=True)
21+
project = Project(file=filename,raft=False)
2222

2323
# plot in 2d and 3d
2424
project.plot2d()
25-
project.plot3d(fowt=True)
25+
#project.plot3d(fowt=True)
2626

2727
plt.show()

famodel/famodel_base.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ def attach(self, object, r_rel=[0,0], end=None):
244244
'''
245245
# Make sure it's not already attached (note this doesn't distinguish end A/B)
246246
if object.id in self.attachments:
247-
raise Exception(f"Object {object.id} is already attached to {self.id}")
247+
return # for bridles, the mooring will already be attached to platform
248+
# for second bridle section
249+
# raise Exception(f"Object {object.id} is already attached to {self.id}")
248250

249251

250252
# Attach the object
@@ -679,10 +681,16 @@ def addSubcomponents(self, items, iA=[0], iB=[-1]):
679681
subitem.part_of = self
680682
else:
681683
item.part_of = self
682-
683684
# Assign ends
684-
self.subcons_A = list([items[0]]) # subcomponent for end A (can be multiple)
685-
self.subcons_B = list([items[-1]]) # subcomponent for end B (can be multiple)
685+
if isinstance(items[0],list):
686+
self.subcons_A = [it[0] for it in items[0]] # subcomponent for end A (can be multiple)
687+
else:
688+
self.subcons_A = list([items[0]]) # subcomponents for end A (can be multiple)
689+
if isinstance(items[-1],list):
690+
self.subcons_B = [it[-1] for it in items[-1]] # subcomponent for end B (can be multiple)
691+
else:
692+
self.subcons_B = list([items[-1]]) # subcomponent for end B (can be multiple)
693+
686694

687695
'''
688696
# Make sure the subcomponents ends are connected appropriately
@@ -728,7 +736,15 @@ def findEnd(self, object):
728736
'''Checks if object is a subcomponent of self and which end it's at.'''
729737

730738
if not object in self.subcomponents:
731-
raise Exception("This object is not a subcomponent of this edge!")
739+
obj_in = False
740+
for sub in self.subcomponents:
741+
if isinstance(sub,list):
742+
for subsub in sub:
743+
if object in subsub:
744+
obj_in = True
745+
break
746+
if not obj_in:
747+
raise Exception("This object is not a subcomponent of this edge!")
732748

733749
if any([object is con for con in self.subcons_A]):
734750
end = 0

famodel/helpers.py

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -753,12 +753,18 @@ def getMoorings(lcID, lineConfigs, connectorTypes, pfID, proj):
753753
lineLast = 0
754754
elif 'subsections' in lc:
755755
# TODO: LHS: ERROR CHECKING FOR ORDER OF COMPONENTS PROVIDED WITHIN SUBSECTIONS, ADD IN NEEDED CONNECTORS!!
756+
757+
if lineLast and k != 0:
758+
# if this is not the first section AND last section was a line, add a empty connector first
759+
config.append({})
760+
lineLast = 0
756761
config.append([])
757762
sublineLast = [lineLast]*len(lc['subsections']) # to check if there was a connector provided before this
758763
for ii,sub in enumerate(lc['subsections']):
759764
config[-1].append([])
760765
for subsub in sub:
761-
if 'connectorType' in subsub:
766+
if 'connectorType' in subsub and sublineLast[ii]:
767+
cID = subsub['connectorType']
762768
if cID in connectorTypes:
763769
cID = subsub['connectorType']
764770
config[-1][-1].append(connectorTypes[cID])
@@ -771,8 +777,13 @@ def getMoorings(lcID, lineConfigs, connectorTypes, pfID, proj):
771777
except Exception as e:
772778
raise Exception(f"Connector type {cID} not found in connector_types dictionary, and getPointProps raised the following exception:",e)
773779
sublineLast[ii] = 0
780+
elif 'connectorType' in subsub and not sublineLast[ii]:
781+
raise Exception('Previous section had a connector, two connectors cannot be listed in a row')
774782
elif 'type' or 'mooringFamily' in subsub:
775-
lt = MooringProps(subsub)
783+
if sublineLast[ii]:
784+
# add empty connector
785+
config[-1][-1].append({})
786+
lt = MooringProps(subsub,proj.lineTypes, proj.rho_water, proj.g)
776787
config[-1][-1].append({'type':lt,
777788
'L': subsub['length']})
778789
sublineLast[ii] = 1
@@ -937,23 +948,24 @@ def attachFairleads(moor, end, platform, fair_ID_start=None, fair_ID=None, fair_
937948
def calc_heading(pointA, pointB):
938949
'''calculate a heading from points, if pointA or pointB is a list of points,
939950
the average of those points will be used for that end'''
940-
if isinstance(pointA[0],list) or isinstance(pointA[0],np.ndarray):
941-
pointAx = sum([x[0] for x in pointA])/len(pointA)
942-
pointAy = sum([x[1] for x in pointA])/len(pointA)
943-
else:
944-
pointAx = pointA[0]
945-
pointAy = pointA[1]
946-
if isinstance(pointB[0],list) or isinstance(pointB[0],np.ndarray):
947-
pointBx = sum([x[0] for x in pointB])/len(pointB)
948-
pointBy = sum([x[1] for x in pointB])/len(pointB)
949-
else:
950-
pointBx = pointB[0]
951-
pointBy = pointB[1]
952-
953-
dists = np.array([pointAx,pointAy]) - np.array([pointBx,pointBy])
951+
# calculate the midpoint of the point(s) on each end first
952+
pointAmid = calc_midpoint(pointA)
953+
pointBmid = calc_midpoint(pointB)
954+
dists = np.array(pointAmid) - np.array(pointBmid)
954955
headingB = np.pi/2 - np.arctan2(dists[1], dists[0])
955956

956957
return(headingB)
958+
959+
def calc_midpoint(point):
960+
'''Calculates the midpoint of a list of points'''
961+
if isinstance(point[0],list) or isinstance(point[0],np.ndarray):
962+
pointx = sum([x[0] for x in point])/len(point)
963+
pointy = sum([x[1] for x in point])/len(point)
964+
else:
965+
pointx = point[0]
966+
pointy = point[1]
967+
968+
return([pointx,pointy])
957969

958970

959971
def route_around_anchors(proj, anchor=True, cable=True, padding=50):
@@ -1003,7 +1015,6 @@ def angle(pt):
10031015
# determine relative positions of new routing points among other routing points
10041016
rel_dist = []
10051017
orig_coords = []
1006-
breakpoint()
10071018
for i,x in enumerate(proj.cableList[name].subcomponents[2].x):
10081019
y = proj.cableList[name].subcomponents[2].y[i]
10091020
rel_dist.append(cab.line_locate_point(sh.Point([x,y])))

famodel/mooring/mooring.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from moorpy import helpers
77
from famodel.mooring.connector import Connector, Section
88
from famodel.famodel_base import Edge
9+
from famodel.helpers import calc_midpoint
910

1011
class Mooring(Edge):
1112
'''
@@ -281,8 +282,9 @@ def reposition(self, r_center=None, heading=None, project=None,
281282
r_centerA = self.attached_to[0].r
282283
r_centerB = self.attached_to[1].r
283284

285+
fairs = True if len(self.subcons_B[0].attachments)>1 else False
284286
# if there is no fairlead object, use traditional method to determine new fairlead location and set it, otherwise end B should be set already
285-
if not len(self.subcons_B[0].attachments) > 1:
287+
if not fairs:
286288
# create fairlead radius list for end A and end B if needed
287289
if not rad_fair:
288290
rad_fair = [self.attached_to[x].rFair if (hasattr(self.attached_to[x],'rFair') and self.attached_to[x].rFair) else 0 for x in range(2)]
@@ -324,7 +326,10 @@ def reposition(self, r_center=None, heading=None, project=None,
324326
self.setEndPosition(np.hstack([r_centerA[:2] - rad_fair[0]*u, z_fair[0] + r_centerA[2]]),'a')
325327

326328
else: # otherwise just set the anchor position based on a set spacing (NEED TO UPDATE THE ANCHOR DEPTH AFTER!)
327-
xy_loc = self.rB[:2] + self.span*u #r_centerB[:2] + (self.span + rad_fair[1])*u
329+
if not fairs:
330+
xy_loc = self.rB[:2] + self.span*u #r_centerB[:2] + (self.span + rad_fair[1])*u
331+
else:
332+
xy_loc = calc_midpoint([sub.r[:2] for sub in self.subcons_B]) + self.span*u
328333
if project:
329334
self.dd['zAnchor'] = -project.getDepthAtLocation(xy_loc[0],xy_loc[1])
330335
self.z_anch = self.dd['zAnchor']
@@ -1154,7 +1159,7 @@ def convertSubcomponents(self, subs_list):
11541159
if isinstance(subsub, list):
11551160
for k, subsubsub in enumerate(subsub):
11561161

1157-
if 'L' in sub:
1162+
if 'L' in subsubsub:
11581163
id = '_'.join(['S',*[str(l) for l in [i,j,k]]])
11591164
# this is a section
11601165
subs_list[i][j][k] = self.addSection(subsubsub['L'],

famodel/project.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -655,10 +655,10 @@ def loadDesign(self, d, raft=True):
655655
moor.attachTo(anchor,end='A')
656656
# attach platform
657657
fairsB = attachFairleads(moor,
658-
1,
659-
PF[0],
660-
fair_ID_start=PF[0].id+'_F',
661-
fair_inds=arrayMooring[j]['fairleadB'])
658+
1,
659+
PF[0],
660+
fair_ID_start=PF[0].id+'_F',
661+
fair_inds=arrayMooring[j]['fairleadB'])
662662

663663
# determine heading
664664
headingB = calc_heading(anchor.r[:2],[f.r[:2] for f in fairsB])
@@ -2187,8 +2187,15 @@ def plot2d(self, ax=None, plot_seabed=True,plot_bathymetry=True, plot_boundary=T
21872187
mooring.ss.drawLine2d(0, ax, color="k", endpoints=False,
21882188
Xuvec=[1,0,0], Yuvec=[0,1,0],label='Mooring Line')
21892189
else: # simple line plot
2190-
ax.plot([mooring.rA[0], mooring.rB[0]],
2191-
[mooring.rA[1], mooring.rB[1]], 'k', lw=0.5, label='Mooring Line')
2190+
if len(mooring.subcons_B[0].attachments)>1:
2191+
# there are fairleads, plot from their locations
2192+
for i in mooring.i_sec:
2193+
sec = mooring.getSubcomponent(i)
2194+
ax.plot([sec.rA[0],sec.rB[0]],
2195+
[sec.rA[1],sec.rB[1]])
2196+
else:
2197+
ax.plot([mooring.rA[0], mooring.rB[0]],
2198+
[mooring.rA[1], mooring.rB[1]], 'k', lw=0.5, label='Mooring Line')
21922199

21932200
if plot_anchors:
21942201
for anchor in self.anchorList.values():

0 commit comments

Comments
 (0)