Ejemplo n.º 1
0
def test_catenary_symmetricU():
    '''Tests the U shaped line with seabed contact against a simulation of half the line'''
    
    (fAH1, fAV1, fBH1, fBV1, info1) = catenary( 50, 20,  65, 1e12, 100.0, CB=  0, Tol=0.00001, MaxIter=50)
    (fAHU, fAVU, fBHU, fBVU, infoU) = catenary(100,  0, 130, 1e12, 100.0, CB=-20, Tol=0.00001, MaxIter=50)

    assert_allclose([fAHU, fAVU, fBHU, fBVU], [-fBH1, fBV1, fBH1, fBV1], rtol=1e-05, atol=0, verbose=True)
Ejemplo n.º 2
0
    def staticSolve(self, reset=False):
        '''Solves static equilibrium of line. Sets the end forces of the line based on the end points' positions.

        Parameters
        ----------
        reset : boolean, optional
            Determines if the previous fairlead force values will be used for the catenary iteration. The default is False.

        Raises
        ------
        LineError
            If the horizontal force at the fairlead (HF) is less than 0

        Returns
        -------
        None.

        '''

        depth = self.sys.depth
        
        dr =  self.rB - self.rA                 
        LH = np.hypot(dr[0], dr[1])     # horizontal spacing of line ends
        LV = dr[2]                # vertical offset from end A to end B

        if self.rA[2] < -depth:
            raise LineError("Line {} end A is lower than the seabed.".format(self.number))
        elif self.rB[2] < -depth:
            raise LineError("Line {} end B is lower than the seabed.".format(self.number))
        elif np.min([self.rA[2],self.rB[2]]) > -depth:
            self.cb = -depth - np.min([self.rA[2],self.rB[2]])   # if this line's lower end is off the seabed, set cb negative and to the distance off the seabed
        elif self.cb < 0:   # if a line end is at the seabed, but the cb is still set negative to indicate off the seabed
            self.cb = 0.0     # set to zero so that the line includes seabed interaction.
        
        
        if self.HF < 0:  # or self.VF < 0:  <<<<<<<<<<< it shouldn't matter if VF is negative - this could happen for buoyant lines, etc.
            raise LineError("Line HF cannot be negative") # this could be a ValueError too...
            
        if reset==True:   # Indicates not to use previous fairlead force values to start catenary 
            self.HF = 0   # iteration with, and insteady use the default values.
            
        try:
            (fAH, fAV, fBH, fBV, info) = catenary(LH, LV, self.L, self.sys.lineTypes[self.type].EA, self.sys.lineTypes[self.type].w, 
                                                  CB=self.cb, HF0=self.HF, VF0=self.VF)   # call line model
        except CatenaryError as error:
            raise LineError(self.number, error.message)
            
        self.th = np.arctan2(dr[1],dr[0])  # probably a more efficient way to handle this <<<
        self.HF = info["HF"]
        self.VF = info["VF"]
        self.jacobian = info["jacobian"]
        self.LBot = info["LBot"]
        self.info = info
            
        self.fA[0] = fAH*dr[0]/LH
        self.fA[1] = fAH*dr[1]/LH
        self.fA[2] = fAV
        self.fB[0] = fBH*dr[0]/LH
        self.fB[1] = fBH*dr[1]/LH
        self.fB[2] = fBV
Ejemplo n.º 3
0
 def getLineCoords(self, Time):    # formerly UpdateLine
     '''Gets the updated line coordinates for drawing and plotting purposes.'''
 
     # if a quasi-static analysis, just call the catenary function to return the line coordinates
     if self.qs==1:
     
         depth = self.sys.depth
     
         dr =  self.rB - self.rA                 
         LH = np.hypot(dr[0], dr[1])     # horizontal spacing of line ends
         LV = dr[2]                      # vertical offset from end A to end B
         
         if np.min([self.rA[2],self.rB[2]]) > -depth:
             self.cb = -depth - np.min([self.rA[2],self.rB[2]])   # if this line's lower end is off the seabed, set cb negative and to the distance off the seabed
         elif self.cb < 0:   # if a line end is at the seabed, but the cb is still set negative to indicate off the seabed
             self.cb = 0.0     # set to zero so that the line includes seabed interaction.
     
         try:
             (fAH, fAV, fBH, fBV, info) = catenary(LH, LV, self.L, self.sys.lineTypes[self.type].EA, 
                                               self.sys.lineTypes[self.type].w, self.cb, HF0=self.HF, VF0=self.VF, nNodes=self.nNodes, plots=1) 
         except CatenaryError as error:
             raise LineError(self.number, error.message)
         
         Xs = self.rA[0] + info["X"]*dr[0]/LH
         Ys = self.rA[1] + info["X"]*dr[1]/LH
         Zs = self.rA[2] + info["Z"]
         
         return Xs, Ys, Zs
         
     # otherwise, count on read-in time-series data
     else:
         # figure out what time step to use
         ts = self.getTimestep(Time)
         
         # drawing rods
         if self.isRod > 0:
         
             k1 = np.array([ self.xp[ts,-1]-self.xp[ts,0], self.yp[ts,-1]-self.yp[ts,0], self.zp[ts,-1]-self.zp[ts,0] ]) / self.length # unit vector
             
             k = np.array(k1) # make copy
         
             Rmat = np.array(rotationMatrix(0, np.arctan2(np.hypot(k[0],k[1]), k[2]), np.arctan2(k[1],k[0])))  # <<< should fix this up at some point, MattLib func may be wrong
             
             # make points for appropriately sized cylinder
             d = self.sys.lineTypes[self.type].d
             Xs, Ys, Zs = makeTower(self.length, np.array([d, d]))
             
             # translate and rotate into proper position for Rod
             coords = np.vstack([Xs, Ys, Zs])
             newcoords = np.matmul(Rmat,coords)
             Xs = newcoords[0,:] + self.xp[ts,0]
             Ys = newcoords[1,:] + self.yp[ts,0]
             Zs = newcoords[2,:] + self.zp[ts,0]
             
             return Xs, Ys, Zs
             
         # drawing lines
         else:
             
             return self.xp[ts,:], self.yp[ts,:], self.zp[ts,:]
Ejemplo n.º 4
0
def test_catenary_solutions(index):
    '''Run each of the test parameter sets with the catenary function and compare results to expected values.'''

    ins = indata[index]
        
    (fAH, fAV, fBH, fBV, info) = catenary( *ins[:5], CB=ins[5], HF0=ins[6], VF0=ins[7], Tol=0.0001, MaxIter=50, plots=3)
        
    print(f"ProfileType is {info['ProfileType']}")
    assert_allclose([fAH, fAV, fBH, fBV, info['LBot']], desired[index], rtol=1e-05, atol=0, verbose=True)
Ejemplo n.º 5
0
Archivo: line.py Proyecto: NREL/MoorPy
    def getLineTens(self):
        '''Calls the catenary function to return the tensions of the Line for a quasi-static analysis'''

        # >>> this can probably be done using data already generated by static Solve <<<

        depth = self.sys.depth
    
        dr =  self.rB - self.rA                 
        LH = np.hypot(dr[0], dr[1])     # horizontal spacing of line ends
        LV = dr[2]                      # vertical offset from end A to end B
        
        if np.min([self.rA[2],self.rB[2]]) > -depth:
            self.cb = -depth - np.min([self.rA[2],self.rB[2]])   # if this line's lower end is off the seabed, set cb negative and to the distance off the seabed
        elif self.cb < 0:   # if a line end is at the seabed, but the cb is still set negative to indicate off the seabed
            self.cb = 0.0     # set to zero so that the line includes seabed interaction.
    
        try:
            (fAH, fAV, fBH, fBV, info) = catenary(LH, LV, self.L, self.sys.lineTypes[self.type].EA, 
                                              self.sys.lineTypes[self.type].w, self.cb, HF0=self.HF, VF0=self.VF, nNodes=self.nNodes, plots=1) 
        except CatenaryError as error:
            raise LineError(self.number, error.message)

        Ts = info["Te"]
        return Ts
Ejemplo n.º 6
0
Archivo: line.py Proyecto: NREL/MoorPy
    def staticSolve(self, reset=False, tol=0.0001, profiles=0):
        '''Solves static equilibrium of line. Sets the end forces of the line based on the end points' positions.

        Parameters
        ----------
        reset : boolean, optional
            Determines if the previous fairlead force values will be used for the catenary iteration. The default is False.

        tol : float
            Convergence tolerance for catenary solver measured as absolute error of x and z values in m.
            
        profiles : int
            Values greater than 0 signal for line profile data to be saved (used for plotting, getting distributed tensions, etc).

        Raises
        ------
        LineError
            If the horizontal force at the fairlead (HF) is less than 0

        Returns
        -------
        None.

        '''

        depth = self.sys.depth
        
        dr =  self.rB - self.rA                 
        LH = np.hypot(dr[0], dr[1])     # horizontal spacing of line ends
        LV = dr[2]                # vertical offset from end A to end B

        if self.rA[2] < -depth:
            raise LineError("Line {} end A is lower than the seabed.".format(self.number))
        elif self.rB[2] < -depth:
            raise LineError("Line {} end B is lower than the seabed.".format(self.number))
        elif np.min([self.rA[2],self.rB[2]]) > -depth:
            self.cb = -depth - np.min([self.rA[2],self.rB[2]])   # if this line's lower end is off the seabed, set cb negative and to the distance off the seabed
        elif self.cb < 0:   # if a line end is at the seabed, but the cb is still set negative to indicate off the seabed
            self.cb = 0.0     # set to zero so that the line includes seabed interaction.
        
        
        if self.HF < 0:  # or self.VF < 0:  <<<<<<<<<<< it shouldn't matter if VF is negative - this could happen for buoyant lines, etc.
            raise LineError("Line HF cannot be negative") # this could be a ValueError too...
            
        if reset==True:   # Indicates not to use previous fairlead force values to start catenary 
            self.HF = 0   # iteration with, and insteady use the default values.
            
        try:
            (fAH, fAV, fBH, fBV, info) = catenary(LH, LV, self.L, self.sys.lineTypes[self.type].EA, self.sys.lineTypes[self.type].w, 
                                                  CB=self.cb, Tol=tol, HF0=self.HF, VF0=self.VF, plots=profiles)   # call line model
        except CatenaryError as error:
            raise LineError(self.number, error.message)
            
        self.th = np.arctan2(dr[1],dr[0])  # probably a more efficient way to handle this <<<
        self.HF = info["HF"]
        self.VF = info["VF"]
        self.KA2 = info["stiffnessA"]
        self.KB2 = info["stiffnessB"]
        self.LBot = info["LBot"]
        self.info = info
            
        self.fA[0] = fAH*dr[0]/LH
        self.fA[1] = fAH*dr[1]/LH
        self.fA[2] = fAV
        self.fB[0] = fBH*dr[0]/LH
        self.fB[1] = fBH*dr[1]/LH
        self.fB[2] = fBV
        self.TA = np.sqrt(fAH*fAH + fAV*fAV) # end tensions
        self.TB = np.sqrt(fBH*fBH + fBV*fBV)
        
        # ----- compute 3d stiffness matrix for both line ends (3 DOF + 3 DOF) -----
        
        # solve for required variables to set up the perpendicular stiffness. Keep it horizontal
        #L_xy = np.linalg.norm(self.rB[:2] - self.rA[:2])
        #T_xy = np.linalg.norm(self.fB[:2])
        
        # create the rotation matrix based on the heading angle that the line is from the horizontal
        R = rotationMatrix(0,0,self.th)
        
        # initialize the line's analytic stiffness matrix in the "in-line" plane then rotate the matrix to be about the global frame [K'] = [R][K][R]^T
        def from2Dto3Drotated(K2D, Kt):
            K2 = np.array([[K2D[0,0], 0 , K2D[0,1]],
                           [  0     , Kt,   0     ],
                           [K2D[1,0], 0 , K2D[1,1]]])
            return np.matmul(np.matmul(R, K2), R.T)
        
        self.KA  = from2Dto3Drotated(info['stiffnessA'], -fBH/LH)   # stiffness matrix describing reaction force on end A due to motion of end A
        self.KB  = from2Dto3Drotated(info['stiffnessB'], -fBH/LH)   # stiffness matrix describing reaction force on end B due to motion of end B
        self.KAB = from2Dto3Drotated(info['stiffnessAB'], fBH/LH)  # stiffness matrix describing reaction force on end B due to motion of end A
                
        #self.K6 = np.block([[ from2Dto3Drotated(self.KA),  from2Dto3Drotated(self.KAB.T)],
        #                    [ from2Dto3Drotated(self.KAB), from2Dto3Drotated(self.KB)  ]])
        
        
        
        if profiles > 1:
            import matplotlib.pyplot as plt
            plt.plot(info['X'], info['Z'])
            plt.show()