diff --git a/famodel/mooring/mooring.py b/famodel/mooring/mooring.py index 6d0cb722..35331fbd 100644 --- a/famodel/mooring/mooring.py +++ b/famodel/mooring/mooring.py @@ -187,7 +187,7 @@ def setSectionType(self, lineType, i): def reposition(self, r_center=None, heading=None, project=None, - degrees=False, rad_fair=[], **kwargs): + degrees=False, rad_fair=[], z_fair=[], **kwargs): '''Adjusts mooring position based on changed platform location or heading. It can call a custom "adjuster" function if one is provided. Otherwise it will just update the end positions. @@ -208,6 +208,10 @@ def reposition(self, r_center=None, heading=None, project=None, fairlead radius of node connected on each end of the mooring line (list should be length 2) If not provided, the fairlead radius will be determined from the attached nodes' listed fairlead radius (or, if it's an anchor, 0) + z_fair : list, optional + fairlead depth of node connected on each end of the mooring line (list should be length 2) + If not provided, the fairlead depth will be determined from the attached nodes' listed + fairlead depths (or, if it's an anchor, 0) **kwargs : dict Additional arguments passed through to the designer function. ''' @@ -232,9 +236,10 @@ def reposition(self, r_center=None, heading=None, project=None, # create fairlead radius list for end A and end B if needed if not rad_fair: 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)] - + if not z_fair: + z_fair = [self.attached_to[x].zFair if (hasattr(self.attached_to[x],'zFair') and self.attached_to[x].zFair) else 0 for x in range(2)] # Set the updated end B location - self.setEndPosition(np.hstack([r_centerB + rad_fair[1]*u, self.z_fair]), 'b') + self.setEndPosition(np.hstack([r_centerB + rad_fair[1]*u, z_fair[1]]), 'b') # Run custom function to update the mooring design (and anchor position) # this would also szie the anchor maybe? @@ -242,7 +247,7 @@ def reposition(self, r_center=None, heading=None, project=None, self.adjuster(self, r_centerB, u, project=project, **kwargs) elif self.shared == 1: # set position of end A at platform end A - self.setEndPosition(np.hstack([r_centerA - rad_fair[0]*u, self.z_fair]),'a') + self.setEndPosition(np.hstack([r_centerA - rad_fair[0]*u, z_fair[0]]),'a') else: # otherwise just set the anchor position based on a set spacing (NEED TO UPDATE THE ANCHOR DEPTH AFTER!) xy_loc = r_centerB + self.rad_anch*u diff --git a/famodel/project.py b/famodel/project.py index cdd368a5..c9fd08a1 100644 --- a/famodel/project.py +++ b/famodel/project.py @@ -600,6 +600,8 @@ def getAnchors(lineAnch, mc=None,aNum=0): # attach turbine to platform self.platformList[arrayInfo[i]['ID']].attach(self.turbineList[turb_name]) self.platformList[arrayInfo[i]['ID']].entity = 'FOWT' + elif arrayInfo[i]['turbineID'] < 0: # (buoy) + self.platformList[arrayInfo[i]['ID']].entity = 'buoy' else: # for now, assume it's an OSS (To be changed!!) self.platformList[arrayInfo[i]['ID']].entity = 'OSS' @@ -745,8 +747,9 @@ def getAnchors(lineAnch, mc=None,aNum=0): # set line anchor type and get dictionary of anchor information lineAnch = arrayAnchor[k]['type'] ad = getAnchors(lineAnch,aNum=aNum) # call method to create dictionary - #mc.z_anch = -zAnew # create anchor object + zAnew = self.getDepthAtLocation(aloc[0], aloc[1]) + mc.z_anch = -zAnew self.anchorList[arrayAnchor[aNum]['ID']] = Anchor(dd=ad, r=[aloc[0],aloc[1],-zAnew], aNum=aNum,id=arrayAnchor[aNum]['ID']) # attach mooring object to anchor mc.attachTo(self.anchorList[(arrayAnchor[aNum]['ID'])],end='A') @@ -2560,11 +2563,18 @@ def getMoorPyArray(self,bodyInfo=None,plt=0, pristineLines=True,cables=0): wflag = 0 # warning flag has not yet been printed (prevent multiple printings of same hydrostatics warning) for i,body in enumerate(self.platformList): # make all the bodies up front - i is index in dictionary, body is key (name of platform) PF = self.platformList[body] + dd = getattr(PF, 'dd', None) # Check if there is a design dictionary for this body # add a moorpy body at the correct location r6 = [PF.r[0],PF.r[1],0,0,0,0] # use bodyInfo dictionary to create moorpy body if given if bodyInfo: - self.ms.addBody(-1,r6,m=bodyInfo[body]['m'],v=bodyInfo[body]['v'],rCG=np.array(bodyInfo[body]['rCG']),rM=np.array(bodyInfo[body]['rM']),AWP=bodyInfo[body]['AWP']) + if not PF.entity=="FOWT": + r6[2] = bodyInfo[body]['rCG'][-1] + self.ms.addBody(-1,r6,m=bodyInfo[body]['m'],v=bodyInfo[body]['v'],rCG=np.array(bodyInfo[body]['rCG']),rM=np.array(bodyInfo[body]['rM']),AWP=bodyInfo[body]['AWP']) + else: + self.ms.addBody(-1,r6,m=bodyInfo[body]['m'],v=bodyInfo[body]['v'],rCG=np.array(bodyInfo[body]['rCG']),rM=np.array(bodyInfo[body]['rM']),AWP=bodyInfo[body]['AWP']) + elif 'm' in dd and 'v' in dd: + self.ms.addBody(-1, r6,m=PF.dd['m'],v=PF.dd['v']) elif not bodyInfo and wflag == 0: # default to UMaine VolturnUS-S design hydrostatics info print('No hydrostatics information given, so default body hydrostatics from UMaine VolturnUS-S will be used.') wflag = 1 @@ -3706,19 +3716,23 @@ def arrayWatchCircle(self,plot=False, ang_spacing=45, RNAheight=150, if not self.ms: self.getMoorPyArray() - + + # apply thrust force to platforms at specified angle intervals for i,ang in enumerate(angs): print('Analyzing platform offsets at angle ',ang) fx = thrust*np.cos(np.radians(ang)) fy = thrust*np.sin(np.radians(ang)) - + # add thrust force and moment to the body - for body in self.ms.bodyList: - body.f6Ext = np.array([fx, fy, 0, fy*RNAheight, fx*RNAheight, 0]) # apply an external force on the body [N] + for pf in self.platformList.values(): + if pf.entity.upper() == 'FOWT': + pf.body.f6Ext = np.array([fx, fy, 0, fy*RNAheight, fx*RNAheight, 0]) # apply an external force on the body [N] + # solve equilibrium self.ms.solveEquilibrium3(DOFtype='both') - + self.ms.plot(draw_seabed=False) + plt.show() # save info if requested if SFs: # get loads on anchors (may be shared) @@ -4094,7 +4108,7 @@ def gothroughlist(dat): # this is not an empty connector if not 'type' in conf['connectors'][i]: # make a new connector type - connTypes[str(int(len(connTypes)))] = dict(conf['connectors'][i]) + connTypes[str(int(len(connTypes))+1)] = dict(conf['connectors'][i]) ctn = str(int(len(connTypes))) # connector type name else: ctn = str(conf['connectors'][i]['type']) @@ -4123,7 +4137,7 @@ def gothroughlist(dat): if not 'type' in conf['connectors'][i+1]: # make a new connector type #conf['connectors'][i+1] = cleanDataTypes(conf['connectors'][i+1]) - connTypes[str(len(connTypes))] = conf['connectors'][i+1] + connTypes[str(len(connTypes))] = dict(conf['connectors'][i+1]) ctn = str(int(len(connTypes))) else: ctn = conf['connectors'][i+1]['type']