def getStiffnessA(self, lines_only=False): '''Gets the analytical stiffness matrix of the Body with other objects fixed. Returns ------- K : matrix 6x6 analytic stiffness matrix. ''' #print("Getting Body "+str(self.number)+" stiffness matrix...") K = np.zeros([6, 6]) for PointID, rPointRel in zip(self.attachedP, self.rPointRel): r = rotatePosition( rPointRel, self.r6[3:] ) # relative position of Point about body ref point in unrotated reference frame f3 = self.sys.pointList[PointID - 1].getForces( ) # total force on point (for additional rotational stiffness term due to change in moment arm) K3 = self.sys.pointList[ PointID - 1].getStiffnessA() # local 3D stiffness matrix of the point # following are from functions translateMatrix3to6 H = getH(r) K[:3, :3] += K3 K[:3, 3:] += np.matmul( K3, H ) # only add up one off-diagonal sub-matrix for now, then we'll mirror at the end K[3:, 3:] += np.matmul(np.matmul(H, K3), H.T) + np.matmul( getH(f3), H.T) #K[3:,3:] += np.matmul(np.matmul(H, K3), H.T) - np.matmul( getH(f3), H) # <<< should be the same K[3:, :3] = K[:3, 3:].T # copy over other off-diagonal sub-matrix if lines_only == False: # rotational stiffness effect of weight rCG_rotated = rotatePosition( self.rCG, self.r6[3:] ) # relative position of CG about body ref point in unrotated reference frame Kw = -np.matmul(getH([0, 0, -self.m * self.sys.g]), getH(rCG_rotated)) # rotational stiffness effect of buoyancy at metacenter rM_rotated = rotatePosition( self.rM, self.r6[3:] ) # relative position of metacenter about body ref point in unrotated reference frame Kb = -np.matmul(getH([0, 0, self.sys.rho * self.sys.g * self.v]), getH(rM_rotated)) # hydrostatic heave stiffness (if AWP is nonzero) Kwp = self.sys.rho * self.sys.g * self.AWP K[3:, 3:] += Kw + Kb K[2, 2] += Kwp return K
def getForces(self, lines_only=False): '''Sums the forces and moments on the Body, including its own plus those from any attached objects. Parameters ---------- lines_only : boolean, optional An option for calculating forces from just the mooring lines or not. The default is False. Returns ------- f6 : array The 6DOF forces and moments applied to the body in its current position [N, Nm] ''' f6 = np.zeros(6) # TODO: could save time in below by storing the body's rotation matrix when it's position is set rather than # recalculating it in each of the following function calls. if lines_only == False: # add weight, which may result in moments as well as a force rCG_rotated = rotatePosition( self.rCG, self.r6[3:] ) # relative position of CG about body ref point in unrotated reference frame f6 += translateForce3to6DOF(rCG_rotated, np.array([ 0, 0, -self.m * self.sys.g ])) # add to net forces/moments # add buoyancy force and moments if applicable (this can include hydrostatic restoring moments # if rM is considered the metacenter location rather than the center of buoyancy) rM_rotated = rotatePosition( self.rM, self.r6[3:] ) # relative position of metacenter about body ref point in unrotated reference frame f6 += translateForce3to6DOF(rM_rotated, np.array([ 0, 0, self.sys.rho * self.sys.g * self.v ])) # add to net forces/moments # add hydrostatic heave stiffness (if AWP is nonzero) f6[2] -= self.sys.rho * self.sys.g * self.AWP * self.r6[2] # add any externally applied forces/moments (in global orientation) f6 += self.f6Ext # add forces from any attached Points (and their attached lines) for PointID, rPointRel in zip(self.attachedP, self.rPointRel): fPoint = self.sys.pointList[PointID - 1].getForces( lines_only=lines_only) # get net force on attached Point rPoint_rotated = rotatePosition( rPointRel, self.r6[3:] ) # relative position of Point about body ref point in unrotated reference frame f6 += translateForce3to6DOF( rPoint_rotated, fPoint ) # add net force and moment resulting from its position to the Body # All forces and moments on the body should now be summed, and are in global/unrotated orientations. # For application to the body DOFs, convert the moments to be about the body's local/rotated x/y/z axes <<< do we want this in all cases? rotMat = rotationMatrix(*self.r6[3:]) # get rotation matrix for body moment_about_body_ref = np.matmul( rotMat.T, f6[3:] ) # transform moments so that they are about the body's local/rotated axes f6[3:] = moment_about_body_ref # use these moments return f6